cg386cnv.pas 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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 secondtypeconv(var p : ptree);
  27. procedure secondas(var p : ptree);
  28. procedure secondis(var p : ptree);
  29. implementation
  30. uses
  31. cobjects,verbose,globals,systems,
  32. symtable,aasm,types,
  33. hcodegen,temp_gen,pass_2,pass_1,
  34. i386,cgai386,tgeni386;
  35. procedure push_shortstring_length(p:ptree);
  36. var
  37. r : preference;
  38. hightree : ptree;
  39. begin
  40. if is_open_string(p^.resulttype) then
  41. begin
  42. getsymonlyin(p^.symtable,'high'+pvarsym(p^.symtableentry)^.name);
  43. hightree:=genloadnode(pvarsym(srsym),p^.symtable);
  44. firstpass(hightree);
  45. secondpass(hightree);
  46. push_value_para(hightree,false,0);
  47. disposetree(hightree);
  48. { r:=new_reference(highframepointer,highoffset+4);
  49. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,r,R_EDI)));
  50. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI))); }
  51. end
  52. else
  53. begin
  54. push_int(pstringdef(p^.resulttype)^.len);
  55. end;
  56. end;
  57. procedure loadshortstring(p:ptree);
  58. {
  59. Load a string, handles stringdef and orddef (char) types
  60. }
  61. begin
  62. case p^.right^.resulttype^.deftype of
  63. stringdef:
  64. begin
  65. if (p^.right^.treetype=stringconstn) and
  66. (str_length(p^.right)=0) then
  67. exprasmlist^.concat(new(pai386,op_const_ref(
  68. A_MOV,S_B,0,newreference(p^.left^.location.reference))))
  69. else
  70. begin
  71. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  72. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  73. push_shortstring_length(p^.left);
  74. emitcall('FPC_SHORTSTR_COPY',true);
  75. maybe_loadesi;
  76. end;
  77. end;
  78. orddef:
  79. begin
  80. if p^.right^.treetype=ordconstn then
  81. exprasmlist^.concat(new(pai386,op_const_ref(
  82. A_MOV,S_W,p^.right^.value*256+1,newreference(p^.left^.location.reference))))
  83. else
  84. begin
  85. { not so elegant (goes better with extra register }
  86. if (p^.right^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  87. begin
  88. exprasmlist^.concat(new(pai386,op_reg_reg(
  89. A_MOV,S_L,makereg32(p^.right^.location.register),R_EDI)));
  90. ungetregister(p^.right^.location.register);
  91. end
  92. else
  93. begin
  94. exprasmlist^.concat(new(pai386,op_ref_reg(
  95. A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI)));
  96. del_reference(p^.right^.location.reference);
  97. end;
  98. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,8,R_EDI)));
  99. exprasmlist^.concat(new(pai386,op_const_reg(A_OR,S_L,1,R_EDI)));
  100. exprasmlist^.concat(new(pai386,op_reg_ref(
  101. A_MOV,S_W,R_DI,newreference(p^.left^.location.reference))));
  102. end;
  103. end;
  104. else
  105. CGMessage(type_e_mismatch);
  106. end;
  107. end;
  108. {*****************************************************************************
  109. SecondTypeConv
  110. *****************************************************************************}
  111. type
  112. tsecondconvproc = procedure(pto,pfrom : ptree;convtyp : tconverttype);
  113. {$ifndef OLDCNV}
  114. procedure second_int_to_int(pto,pfrom : ptree;convtyp : tconverttype);
  115. var
  116. op : tasmop;
  117. opsize : topsize;
  118. hregister : tregister;
  119. begin
  120. { insert range check if not explicit conversion }
  121. if not(pto^.explizit) then
  122. emitrangecheck(pfrom,pto^.resulttype);
  123. { is the result size smaller ? }
  124. if pto^.resulttype^.size<pfrom^.resulttype^.size then
  125. begin
  126. { only need to set the new size of a register }
  127. if (pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  128. begin
  129. case pto^.resulttype^.size of
  130. 1 : pto^.location.register:=makereg8(pfrom^.location.register);
  131. 2 : pto^.location.register:=makereg16(pfrom^.location.register);
  132. 4 : pto^.location.register:=makereg32(pfrom^.location.register);
  133. end;
  134. end;
  135. end
  136. { is the result size bigger ? }
  137. else if pto^.resulttype^.size>pfrom^.resulttype^.size then
  138. begin
  139. { remove reference }
  140. if not(pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  141. begin
  142. del_reference(pfrom^.location.reference);
  143. { we can do this here as we need no temp inside }
  144. ungetiftemp(pfrom^.location.reference);
  145. end;
  146. { get op and opsize, handle separate for constants, becuase
  147. movz doesn't support constant values }
  148. if (pfrom^.location.loc=LOC_MEM) and (pfrom^.location.reference.isintvalue) then
  149. begin
  150. opsize:=def_opsize(pto^.resulttype);
  151. op:=A_MOV;
  152. end
  153. else
  154. begin
  155. opsize:=def2def_opsize(pfrom^.resulttype,pto^.resulttype);
  156. if opsize in [S_B,S_W,S_L] then
  157. op:=A_MOV
  158. else
  159. if is_signed(pfrom^.resulttype) then
  160. op:=A_MOVSX
  161. else
  162. op:=A_MOVZX;
  163. end;
  164. { load the register we need }
  165. if pfrom^.location.loc<>LOC_REGISTER then
  166. hregister:=getregister32
  167. else
  168. hregister:=pfrom^.location.register;
  169. { set the correct register size and location }
  170. clear_location(pto^.location);
  171. pto^.location.loc:=LOC_REGISTER;
  172. case pto^.resulttype^.size of
  173. 1 : pto^.location.register:=makereg8(hregister);
  174. 2 : pto^.location.register:=makereg16(hregister);
  175. 4 : pto^.location.register:=makereg32(hregister);
  176. end;
  177. { insert the assembler code }
  178. if pfrom^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  179. emit_reg_reg(op,opsize,pfrom^.location.register,pto^.location.register)
  180. else
  181. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  182. newreference(pfrom^.location.reference),pto^.location.register)));
  183. end;
  184. end;
  185. {$else}
  186. procedure maybe_rangechecking(p : ptree;p2,p1 : pdef);
  187. {
  188. produces if necessary rangecheckcode
  189. }
  190. var
  191. hp : preference;
  192. hregister : tregister;
  193. neglabel,poslabel : plabel;
  194. is_register : boolean;
  195. begin
  196. { convert from p2 to p1 }
  197. { range check from enums is not made yet !!}
  198. { and its probably not easy }
  199. if (p1^.deftype<>orddef) or (p2^.deftype<>orddef) then
  200. exit;
  201. { range checking is different for u32bit }
  202. { lets try to generate it allways }
  203. if (cs_check_range in aktlocalswitches) and
  204. { with $R+ explicit type conversations in TP aren't range checked! }
  205. (not(p^.explizit) {or not(cs_tp_compatible in aktmoduleswitches)}) and
  206. ((porddef(p1)^.low>porddef(p2)^.low) or
  207. (porddef(p1)^.high<porddef(p2)^.high) or
  208. (porddef(p1)^.typ=u32bit) or
  209. (porddef(p2)^.typ=u32bit)) then
  210. begin
  211. porddef(p1)^.genrangecheck;
  212. is_register:=(p^.location.loc=LOC_REGISTER) or
  213. (p^.location.loc=LOC_CREGISTER);
  214. if porddef(p2)^.typ=u8bit then
  215. begin
  216. if is_register then
  217. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,p^.location.register,R_EDI)))
  218. else
  219. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(p^.location.reference),R_EDI)));
  220. hregister:=R_EDI;
  221. end
  222. else if porddef(p2)^.typ=s8bit then
  223. begin
  224. if is_register then
  225. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_BL,p^.location.register,R_EDI)))
  226. else
  227. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,newreference(p^.location.reference),R_EDI)));
  228. hregister:=R_EDI;
  229. end
  230. { rangechecking for u32bit ?? !!!!!!}
  231. { lets try }
  232. else if (porddef(p2)^.typ=s32bit) or (porddef(p2)^.typ=u32bit) then
  233. begin
  234. if is_register then
  235. hregister:=p^.location.register
  236. else
  237. begin
  238. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),R_EDI)));
  239. hregister:=R_EDI;
  240. end;
  241. end
  242. else if porddef(p2)^.typ=u16bit then
  243. begin
  244. if is_register then
  245. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,p^.location.register,R_EDI)))
  246. else
  247. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,newreference(p^.location.reference),R_EDI)));
  248. hregister:=R_EDI;
  249. end
  250. else if porddef(p2)^.typ=s16bit then
  251. begin
  252. if is_register then
  253. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,p^.location.register,R_EDI)))
  254. else
  255. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,newreference(p^.location.reference),R_EDI)));
  256. hregister:=R_EDI;
  257. end
  258. else internalerror(6);
  259. hp:=new_reference(R_NO,0);
  260. hp^.symbol:=stringdup(porddef(p1)^.getrangecheckstring);
  261. if porddef(p1)^.low>porddef(p1)^.high then
  262. begin
  263. getlabel(neglabel);
  264. getlabel(poslabel);
  265. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hregister,hregister)));
  266. emitl(A_JL,neglabel);
  267. end;
  268. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hp)));
  269. if porddef(p1)^.low>porddef(p1)^.high then
  270. begin
  271. hp:=new_reference(R_NO,0);
  272. hp^.symbol:=stringdup(porddef(p1)^.getrangecheckstring);
  273. { second part here !! }
  274. hp^.offset:=8;
  275. emitl(A_JMP,poslabel);
  276. emitl(A_LABEL,neglabel);
  277. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hp)));
  278. emitl(A_LABEL,poslabel);
  279. end;
  280. end;
  281. end;
  282. procedure second_only_rangecheck(pto,pfrom : ptree;convtyp : tconverttype);
  283. begin
  284. maybe_rangechecking(pto,pfrom^.resulttype,pto^.resulttype);
  285. end;
  286. procedure second_smaller(pto,pfrom : ptree;convtyp : tconverttype);
  287. var
  288. hregister,destregister : tregister;
  289. ref : boolean;
  290. hpp : preference;
  291. begin
  292. ref:=false;
  293. { problems with enums !! }
  294. if (cs_check_range in aktlocalswitches) and
  295. { with $R+ explicit type conversations in TP aren't range checked! }
  296. (not(pto^.explizit) {or not(cs_tp_compatible in aktmoduleswitches)}) and
  297. (pto^.resulttype^.deftype=orddef) and
  298. (pfrom^.resulttype^.deftype=orddef) then
  299. begin
  300. if porddef(pfrom^.resulttype)^.typ=u32bit then
  301. begin
  302. { when doing range checking for u32bit, we have some trouble }
  303. { because BOUND assumes signed values }
  304. { first, we check if the values is greater than 2^31: }
  305. { the u32bit rangenr contains the appropriate rangenr }
  306. porddef(pfrom^.resulttype)^.genrangecheck;
  307. hregister:=R_EDI;
  308. if (pto^.location.loc=LOC_REGISTER) or
  309. (pto^.location.loc=LOC_CREGISTER) then
  310. hregister:=pto^.location.register
  311. else
  312. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  313. newreference(pto^.location.reference),R_EDI)));
  314. hpp:=new_reference(R_NO,0);
  315. hpp^.symbol:=stringdup(porddef(pfrom^.resulttype)^.getrangecheckstring);
  316. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hpp)));
  317. { then we do a normal range check }
  318. porddef(pto^.resulttype)^.genrangecheck;
  319. hpp:=new_reference(R_NO,0);
  320. hpp^.symbol:=stringdup(porddef(pto^.resulttype)^.getrangecheckstring);
  321. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hpp)));
  322. end
  323. else
  324. if ((porddef(pto^.resulttype)^.low>porddef(pfrom^.resulttype)^.low) or
  325. (porddef(pto^.resulttype)^.high<porddef(pfrom^.resulttype)^.high)) then
  326. begin
  327. porddef(pto^.resulttype)^.genrangecheck;
  328. { per default the var is copied to EDI }
  329. hregister:=R_EDI;
  330. if porddef(pfrom^.resulttype)^.typ=s32bit then
  331. begin
  332. if (pto^.location.loc=LOC_REGISTER) or
  333. (pto^.location.loc=LOC_CREGISTER) then
  334. hregister:=pto^.location.register
  335. else
  336. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pto^.location.reference),R_EDI)));
  337. end
  338. else if porddef(pfrom^.resulttype)^.typ=u16bit then
  339. begin
  340. if (pto^.location.loc=LOC_REGISTER) or
  341. (pto^.location.loc=LOC_CREGISTER) then
  342. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,pto^.location.register,R_EDI)))
  343. else
  344. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,
  345. newreference(pto^.location.reference),R_EDI)));
  346. end
  347. else if porddef(pfrom^.resulttype)^.typ=s16bit then
  348. begin
  349. if (pto^.location.loc=LOC_REGISTER) or
  350. (pto^.location.loc=LOC_CREGISTER) then
  351. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,pto^.location.register,R_EDI)))
  352. else
  353. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,
  354. newreference(pto^.location.reference),R_EDI)));
  355. end
  356. else internalerror(6);
  357. hpp:=new_reference(R_NO,0);
  358. hpp^.symbol:=stringdup(porddef(pto^.resulttype)^.getrangecheckstring);
  359. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hpp)));
  360. (*
  361. if (p^.location.loc=LOC_REGISTER) or
  362. (p^.location.loc=LOC_CREGISTER) then
  363. begin
  364. destregister:=pfrom^.location.register;
  365. case convtyp of
  366. tc_s32bit_2_s8bit,
  367. tc_s32bit_2_u8bit:
  368. destregister:=reg32toreg8(destregister);
  369. tc_s32bit_2_s16bit,
  370. tc_s32bit_2_u16bit:
  371. destregister:=reg32toreg16(destregister);
  372. { this was false because destregister is allways a 32bitreg }
  373. tc_s16bit_2_s8bit,
  374. tc_s16bit_2_u8bit,
  375. tc_u16bit_2_s8bit,
  376. tc_u16bit_2_u8bit:
  377. destregister:=reg32toreg8(destregister);
  378. end;
  379. p^.location.register:=destregister;
  380. exit;
  381. *)
  382. end;
  383. end;
  384. { p^.location.loc is already set! }
  385. if (pto^.location.loc=LOC_REGISTER) or
  386. (pto^.location.loc=LOC_CREGISTER) then
  387. begin
  388. destregister:=pfrom^.location.register;
  389. case convtyp of
  390. tc_s32bit_2_s8bit,
  391. tc_s32bit_2_u8bit:
  392. destregister:=reg32toreg8(destregister);
  393. tc_s32bit_2_s16bit,
  394. tc_s32bit_2_u16bit:
  395. destregister:=reg32toreg16(destregister);
  396. tc_s16bit_2_s8bit,
  397. tc_s16bit_2_u8bit,
  398. tc_u16bit_2_s8bit,
  399. tc_u16bit_2_u8bit:
  400. destregister:=reg16toreg8(destregister);
  401. end;
  402. pto^.location.register:=destregister;
  403. end;
  404. end;
  405. procedure second_bigger(pto,pfrom : ptree;convtyp : tconverttype);
  406. var
  407. hregister : tregister;
  408. opsize : topsize;
  409. op : tasmop;
  410. is_register : boolean;
  411. begin
  412. is_register:=pfrom^.location.loc=LOC_REGISTER;
  413. if not(is_register) and (pfrom^.location.loc<>LOC_CREGISTER) then
  414. begin
  415. del_reference(pfrom^.location.reference);
  416. { we can do this here as we need no temp inside second_bigger }
  417. ungetiftemp(pfrom^.location.reference);
  418. end;
  419. { this is wrong !!!
  420. gives me movl (%eax),%eax
  421. for the length(string !!!
  422. use only for constant values }
  423. {Constant cannot be loaded into registers using MOVZX!}
  424. if (pfrom^.location.loc<>LOC_MEM) or (not pfrom^.location.reference.isintvalue) then
  425. case convtyp of
  426. tc_u8bit_2_s32bit,tc_u8bit_2_u32bit :
  427. begin
  428. if is_register then
  429. hregister:=reg8toreg32(pfrom^.location.register)
  430. else hregister:=getregister32;
  431. op:=A_MOVZX;
  432. opsize:=S_BL;
  433. end;
  434. { here what do we do for negative values ? }
  435. tc_s8bit_2_s32bit,tc_s8bit_2_u32bit :
  436. begin
  437. if is_register then
  438. hregister:=reg8toreg32(pfrom^.location.register)
  439. else hregister:=getregister32;
  440. op:=A_MOVSX;
  441. opsize:=S_BL;
  442. end;
  443. tc_u16bit_2_s32bit,tc_u16bit_2_u32bit :
  444. begin
  445. if is_register then
  446. hregister:=reg16toreg32(pfrom^.location.register)
  447. else hregister:=getregister32;
  448. op:=A_MOVZX;
  449. opsize:=S_WL;
  450. end;
  451. tc_s16bit_2_s32bit,tc_s16bit_2_u32bit :
  452. begin
  453. if is_register then
  454. hregister:=reg16toreg32(pfrom^.location.register)
  455. else hregister:=getregister32;
  456. op:=A_MOVSX;
  457. opsize:=S_WL;
  458. end;
  459. tc_s8bit_2_u16bit,
  460. tc_u8bit_2_s16bit,
  461. tc_u8bit_2_u16bit :
  462. begin
  463. if is_register then
  464. hregister:=reg8toreg16(pfrom^.location.register)
  465. else hregister:=reg32toreg16(getregister32);
  466. op:=A_MOVZX;
  467. opsize:=S_BW;
  468. end;
  469. tc_s8bit_2_s16bit :
  470. begin
  471. if is_register then
  472. hregister:=reg8toreg16(pfrom^.location.register)
  473. else hregister:=reg32toreg16(getregister32);
  474. op:=A_MOVSX;
  475. opsize:=S_BW;
  476. end;
  477. end
  478. else
  479. case convtyp of
  480. tc_u8bit_2_s32bit,
  481. tc_s8bit_2_s32bit,
  482. tc_u16bit_2_s32bit,
  483. tc_s16bit_2_s32bit,
  484. tc_u8bit_2_u32bit,
  485. tc_s8bit_2_u32bit,
  486. tc_u16bit_2_u32bit,
  487. tc_s16bit_2_u32bit:
  488. begin
  489. hregister:=getregister32;
  490. op:=A_MOV;
  491. opsize:=S_L;
  492. end;
  493. tc_s8bit_2_u16bit,
  494. tc_s8bit_2_s16bit,
  495. tc_u8bit_2_s16bit,
  496. tc_u8bit_2_u16bit:
  497. begin
  498. hregister:=reg32toreg16(getregister32);
  499. op:=A_MOV;
  500. opsize:=S_W;
  501. end;
  502. end;
  503. if is_register then
  504. begin
  505. emit_reg_reg(op,opsize,pfrom^.location.register,hregister);
  506. end
  507. else
  508. begin
  509. if pfrom^.location.loc=LOC_CREGISTER then
  510. emit_reg_reg(op,opsize,pfrom^.location.register,hregister)
  511. else exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  512. newreference(pfrom^.location.reference),hregister)));
  513. end;
  514. clear_location(pto^.location);
  515. pto^.location.loc:=LOC_REGISTER;
  516. pto^.location.register:=hregister;
  517. maybe_rangechecking(pfrom,pfrom^.resulttype,pto^.resulttype);
  518. end;
  519. {$endif}
  520. var
  521. ltemptoremove : plinkedlist;
  522. procedure second_string_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  523. var
  524. pushed : tpushed;
  525. begin
  526. { does anybody know a better solution than this big case statement ? }
  527. { ok, a proc table would do the job }
  528. case pstringdef(pto^.resulttype)^.string_typ of
  529. st_shortstring:
  530. case pstringdef(pfrom^.resulttype)^.string_typ of
  531. st_shortstring:
  532. begin
  533. stringdispose(pto^.location.reference.symbol);
  534. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  535. del_reference(pfrom^.location.reference);
  536. copyshortstring(pto^.location.reference,pfrom^.location.reference,
  537. pstringdef(pto^.resulttype)^.len,false);
  538. ungetiftemp(pfrom^.location.reference);
  539. end;
  540. st_longstring:
  541. begin
  542. {!!!!!!!}
  543. internalerror(8888);
  544. end;
  545. st_ansistring:
  546. begin
  547. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  548. loadansi2short(pfrom,pto);
  549. { this is done in secondtypeconv (FK)
  550. removetemps(exprasmlist,temptoremove);
  551. destroys:=true;
  552. }
  553. end;
  554. st_widestring:
  555. begin
  556. {!!!!!!!}
  557. internalerror(8888);
  558. end;
  559. end;
  560. st_longstring:
  561. case pstringdef(pfrom^.resulttype)^.string_typ of
  562. st_shortstring:
  563. begin
  564. {!!!!!!!}
  565. internalerror(8888);
  566. end;
  567. st_ansistring:
  568. begin
  569. {!!!!!!!}
  570. internalerror(8888);
  571. end;
  572. st_widestring:
  573. begin
  574. {!!!!!!!}
  575. internalerror(8888);
  576. end;
  577. end;
  578. st_ansistring:
  579. case pstringdef(pfrom^.resulttype)^.string_typ of
  580. st_shortstring:
  581. begin
  582. clear_location(pto^.location);
  583. pto^.location.loc:=LOC_REFERENCE;
  584. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  585. ltemptoremove^.concat(new(ptemptodestroy,init(pto^.location.reference,pto^.resulttype)));
  586. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,0,newreference(pto^.location.reference))));
  587. pushusedregisters(pushed,$ff);
  588. emit_push_lea_loc(pfrom^.location);
  589. emit_push_lea_loc(pto^.location);
  590. emitcall('FPC_SHORTSTR_TO_ANSISTR',true);
  591. maybe_loadesi;
  592. popusedregisters(pushed);
  593. ungetiftemp(pfrom^.location.reference);
  594. end;
  595. st_longstring:
  596. begin
  597. {!!!!!!!}
  598. internalerror(8888);
  599. end;
  600. st_widestring:
  601. begin
  602. {!!!!!!!}
  603. internalerror(8888);
  604. end;
  605. end;
  606. st_widestring:
  607. case pstringdef(pfrom^.resulttype)^.string_typ of
  608. st_shortstring:
  609. begin
  610. {!!!!!!!}
  611. internalerror(8888);
  612. end;
  613. st_longstring:
  614. begin
  615. {!!!!!!!}
  616. internalerror(8888);
  617. end;
  618. st_ansistring:
  619. begin
  620. {!!!!!!!}
  621. internalerror(8888);
  622. end;
  623. st_widestring:
  624. begin
  625. {!!!!!!!}
  626. internalerror(8888);
  627. end;
  628. end;
  629. end;
  630. end;
  631. procedure second_cstring_to_pchar(pto,pfrom : ptree;convtyp : tconverttype);
  632. begin
  633. clear_location(pto^.location);
  634. pto^.location.loc:=LOC_REGISTER;
  635. pto^.location.register:=getregister32;
  636. case pstringdef(pfrom^.resulttype)^.string_typ of
  637. st_shortstring :
  638. begin
  639. inc(pfrom^.location.reference.offset);
  640. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  641. pto^.location.register)));
  642. end;
  643. st_ansistring :
  644. begin
  645. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  646. pto^.location.register)));
  647. end;
  648. st_longstring:
  649. begin
  650. {!!!!!!!}
  651. internalerror(8888);
  652. end;
  653. st_widestring:
  654. begin
  655. {!!!!!!!}
  656. internalerror(8888);
  657. end;
  658. end;
  659. end;
  660. procedure second_string_to_chararray(pto,pfrom : ptree;convtyp : tconverttype);
  661. begin
  662. case pstringdef(pfrom^.resulttype)^.string_typ of
  663. st_shortstring :
  664. begin
  665. inc(pto^.location.reference.offset);
  666. end;
  667. st_ansistring :
  668. begin
  669. {!!!!!!!}
  670. internalerror(8888);
  671. end;
  672. st_longstring:
  673. begin
  674. {!!!!!!!}
  675. internalerror(8888);
  676. end;
  677. st_widestring:
  678. begin
  679. {!!!!!!!}
  680. internalerror(8888);
  681. end;
  682. end;
  683. end;
  684. procedure second_array_to_pointer(pto,pfrom : ptree;convtyp : tconverttype);
  685. begin
  686. del_reference(pfrom^.location.reference);
  687. clear_location(pto^.location);
  688. pto^.location.loc:=LOC_REGISTER;
  689. pto^.location.register:=getregister32;
  690. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  691. pto^.location.register)));
  692. end;
  693. procedure second_pointer_to_array(pto,pfrom : ptree;convtyp : tconverttype);
  694. begin
  695. clear_location(pto^.location);
  696. pto^.location.loc:=LOC_REFERENCE;
  697. clear_reference(pto^.location.reference);
  698. case pfrom^.location.loc of
  699. LOC_REGISTER :
  700. pto^.location.reference.base:=pfrom^.location.register;
  701. LOC_CREGISTER :
  702. begin
  703. pto^.location.reference.base:=getregister32;
  704. emit_reg_reg(A_MOV,S_L,pfrom^.location.register,pto^.location.reference.base);
  705. end
  706. else
  707. begin
  708. del_reference(pfrom^.location.reference);
  709. pto^.location.reference.base:=getregister32;
  710. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  711. pto^.location.reference.base)));
  712. end;
  713. end;
  714. end;
  715. { generates the code for the type conversion from an array of char }
  716. { to a string }
  717. procedure second_chararray_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  718. var
  719. l : longint;
  720. begin
  721. { this is a type conversion which copies the data, so we can't }
  722. { return a reference }
  723. clear_location(pto^.location);
  724. pto^.location.loc:=LOC_MEM;
  725. { first get the memory for the string }
  726. gettempofsizereference(256,pto^.location.reference);
  727. { calc the length of the array }
  728. l:=parraydef(pfrom^.resulttype)^.highrange-
  729. parraydef(pfrom^.resulttype)^.lowrange+1;
  730. if l>255 then
  731. CGMessage(type_e_mismatch);
  732. { write the length }
  733. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,l,
  734. newreference(pto^.location.reference))));
  735. { copy to first char of string }
  736. inc(pto^.location.reference.offset);
  737. { generates the copy code }
  738. { and we need the source never }
  739. concatcopy(pfrom^.location.reference,pto^.location.reference,l,true,false);
  740. { correct the string location }
  741. dec(pto^.location.reference.offset);
  742. end;
  743. procedure second_char_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  744. var
  745. pushed : tpushed;
  746. begin
  747. clear_location(pto^.location);
  748. pto^.location.loc:=LOC_MEM;
  749. case pstringdef(pto^.resulttype)^.string_typ of
  750. st_shortstring :
  751. begin
  752. gettempofsizereference(256,pto^.location.reference);
  753. { call loadstring with correct left and right }
  754. pto^.right:=pfrom;
  755. pto^.left:=pto;
  756. loadshortstring(pto);
  757. pto^.left:=nil; { reset left tree, which is empty }
  758. { pto^.right is not disposed for typeconv !! PM }
  759. disposetree(pto^.right);
  760. pto^.right:=nil;
  761. end;
  762. st_ansistring :
  763. begin
  764. gettempofsizereference(4,pto^.location.reference);
  765. ltemptoremove^.concat(new(ptemptodestroy,init(pto^.location.reference,pto^.resulttype)));
  766. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,0,newreference(pto^.location.reference))));
  767. pushusedregisters(pushed,$ff);
  768. emit_pushw_loc(pfrom^.location);
  769. emitpushreferenceaddr(exprasmlist,pto^.location.reference);
  770. emitcall('FPC_CHAR_TO_ANSISTR',true);
  771. popusedregisters(pushed);
  772. maybe_loadesi;
  773. end;
  774. else
  775. internalerror(4179);
  776. end;
  777. end;
  778. procedure second_int_to_real(pto,pfrom : ptree;convtyp : tconverttype);
  779. var
  780. r : preference;
  781. hregister : tregister;
  782. begin
  783. { for u32bit a solution is to push $0 and to load a comp }
  784. { does this first, it destroys maybe EDI }
  785. hregister:=R_EDI;
  786. if porddef(pfrom^.resulttype)^.typ=u32bit then
  787. push_int(0);
  788. if (pfrom^.location.loc=LOC_REGISTER) or
  789. (pfrom^.location.loc=LOC_CREGISTER) then
  790. begin
  791. case porddef(pfrom^.resulttype)^.typ of
  792. s8bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_BL,pfrom^.location.register,R_EDI)));
  793. u8bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,pfrom^.location.register,R_EDI)));
  794. s16bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,pfrom^.location.register,R_EDI)));
  795. u16bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,pfrom^.location.register,R_EDI)));
  796. u32bit,s32bit:
  797. hregister:=pfrom^.location.register
  798. end;
  799. ungetregister(pfrom^.location.register);
  800. end
  801. else
  802. begin
  803. r:=newreference(pfrom^.location.reference);
  804. case porddef(pfrom^.resulttype)^.typ of
  805. s8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,r,R_EDI)));
  806. u8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,r,R_EDI)));
  807. s16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,r,R_EDI)));
  808. u16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,r,R_EDI)));
  809. u32bit,s32bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  810. end;
  811. del_reference(pfrom^.location.reference);
  812. ungetiftemp(pfrom^.location.reference);
  813. end;
  814. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,hregister)));
  815. r:=new_reference(R_ESP,0);
  816. if porddef(pfrom^.resulttype)^.typ=u32bit then
  817. exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IQ,r)))
  818. else
  819. exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IL,r)));
  820. { better than an add on all processors }
  821. if porddef(pfrom^.resulttype)^.typ=u32bit then
  822. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,8,R_ESP)))
  823. else
  824. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  825. clear_location(pto^.location);
  826. pto^.location.loc:=LOC_FPU;
  827. end;
  828. procedure second_real_to_fix(pto,pfrom : ptree;convtyp : tconverttype);
  829. var
  830. rreg : tregister;
  831. ref : treference;
  832. begin
  833. { real must be on fpu stack }
  834. if (pfrom^.location.loc<>LOC_FPU) then
  835. exprasmlist^.concat(new(pai386,op_ref(A_FLD,S_FL,newreference(pfrom^.location.reference))));
  836. push_int($1f3f);
  837. push_int(65536);
  838. reset_reference(ref);
  839. ref.base:=R_ESP;
  840. exprasmlist^.concat(new(pai386,op_ref(A_FIMUL,S_IL,newreference(ref))));
  841. ref.offset:=4;
  842. exprasmlist^.concat(new(pai386,op_ref(A_FSTCW,S_NO,newreference(ref))));
  843. ref.offset:=6;
  844. exprasmlist^.concat(new(pai386,op_ref(A_FLDCW,S_NO,newreference(ref))));
  845. ref.offset:=0;
  846. exprasmlist^.concat(new(pai386,op_ref(A_FISTP,S_IL,newreference(ref))));
  847. ref.offset:=4;
  848. exprasmlist^.concat(new(pai386,op_ref(A_FLDCW,S_NO,newreference(ref))));
  849. rreg:=getregister32;
  850. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,rreg)));
  851. { better than an add on all processors }
  852. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  853. clear_location(pto^.location);
  854. pto^.location.loc:=LOC_REGISTER;
  855. pto^.location.register:=rreg;
  856. end;
  857. procedure second_real_to_real(pto,pfrom : ptree;convtyp : tconverttype);
  858. begin
  859. case pfrom^.location.loc of
  860. LOC_FPU : ;
  861. LOC_MEM,
  862. LOC_REFERENCE:
  863. begin
  864. floatload(pfloatdef(pfrom^.resulttype)^.typ,
  865. pfrom^.location.reference);
  866. { we have to free the reference }
  867. del_reference(pfrom^.location.reference);
  868. end;
  869. end;
  870. clear_location(pto^.location);
  871. pto^.location.loc:=LOC_FPU;
  872. end;
  873. procedure second_fix_to_real(pto,pfrom : ptree;convtyp : tconverttype);
  874. var
  875. popeax,popebx,popecx,popedx : boolean;
  876. startreg : tregister;
  877. hl : plabel;
  878. r : treference;
  879. begin
  880. if (pfrom^.location.loc=LOC_REGISTER) or
  881. (pfrom^.location.loc=LOC_CREGISTER) then
  882. begin
  883. startreg:=pfrom^.location.register;
  884. ungetregister(startreg);
  885. popeax:=(startreg<>R_EAX) and not (R_EAX in unused);
  886. if popeax then
  887. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  888. { mov eax,eax is removed by emit_reg_reg }
  889. emit_reg_reg(A_MOV,S_L,startreg,R_EAX);
  890. end
  891. else
  892. begin
  893. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  894. pfrom^.location.reference),R_EAX)));
  895. del_reference(pfrom^.location.reference);
  896. startreg:=R_NO;
  897. end;
  898. popebx:=(startreg<>R_EBX) and not (R_EBX in unused);
  899. if popebx then
  900. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  901. popecx:=(startreg<>R_ECX) and not (R_ECX in unused);
  902. if popecx then
  903. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ECX)));
  904. popedx:=(startreg<>R_EDX) and not (R_EDX in unused);
  905. if popedx then
  906. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDX)));
  907. exprasmlist^.concat(new(pai386,op_none(A_CDQ,S_NO)));
  908. emit_reg_reg(A_XOR,S_L,R_EDX,R_EAX);
  909. emit_reg_reg(A_MOV,S_L,R_EAX,R_EBX);
  910. emit_reg_reg(A_SUB,S_L,R_EDX,R_EAX);
  911. getlabel(hl);
  912. emitl(A_JZ,hl);
  913. exprasmlist^.concat(new(pai386,op_const_reg(A_RCL,S_L,1,R_EBX)));
  914. emit_reg_reg(A_BSR,S_L,R_EAX,R_EDX);
  915. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,32,R_CL)));
  916. emit_reg_reg(A_SUB,S_B,R_DL,R_CL);
  917. emit_reg_reg(A_SHL,S_L,R_CL,R_EAX);
  918. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_W,1007,R_DX)));
  919. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_W,5,R_DX)));
  920. exprasmlist^.concat(new(pai386,op_const_reg_reg(A_SHLD,S_W,11,R_DX,R_BX)));
  921. exprasmlist^.concat(new(pai386,op_const_reg_reg(A_SHLD,S_L,20,R_EAX,R_EBX)));
  922. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,20,R_EAX)));
  923. emitl(A_LABEL,hl);
  924. { better than an add on all processors }
  925. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  926. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  927. reset_reference(r);
  928. r.base:=R_ESP;
  929. exprasmlist^.concat(new(pai386,op_ref(A_FLD,S_FL,newreference(r))));
  930. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,8,R_ESP)));
  931. if popedx then
  932. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDX)));
  933. if popecx then
  934. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ECX)));
  935. if popebx then
  936. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EBX)));
  937. if popeax then
  938. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
  939. clear_location(pto^.location);
  940. pto^.location.loc:=LOC_FPU;
  941. end;
  942. procedure second_int_to_fix(pto,pfrom : ptree;convtyp : tconverttype);
  943. var
  944. hregister : tregister;
  945. begin
  946. if (pfrom^.location.loc=LOC_REGISTER) then
  947. hregister:=pfrom^.location.register
  948. else if (pfrom^.location.loc=LOC_CREGISTER) then
  949. hregister:=getregister32
  950. else
  951. begin
  952. del_reference(pfrom^.location.reference);
  953. hregister:=getregister32;
  954. case porddef(pfrom^.resulttype)^.typ of
  955. s8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,newreference(pfrom^.location.reference),
  956. hregister)));
  957. u8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(pfrom^.location.reference),
  958. hregister)));
  959. s16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,newreference(pfrom^.location.reference),
  960. hregister)));
  961. u16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,newreference(pfrom^.location.reference),
  962. hregister)));
  963. u32bit,s32bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  964. hregister)));
  965. {!!!! u32bit }
  966. end;
  967. end;
  968. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,16,hregister)));
  969. clear_location(pto^.location);
  970. pto^.location.loc:=LOC_REGISTER;
  971. pto^.location.register:=hregister;
  972. end;
  973. procedure second_proc_to_procvar(pto,pfrom : ptree;convtyp : tconverttype);
  974. begin
  975. { method pointer ? }
  976. if assigned(pfrom^.left) then
  977. begin
  978. set_location(pto^.location,pfrom^.location);
  979. end
  980. else
  981. begin
  982. clear_location(pto^.location);
  983. pto^.location.loc:=LOC_REGISTER;
  984. pto^.location.register:=getregister32;
  985. del_reference(pfrom^.location.reference);
  986. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  987. newreference(pfrom^.location.reference),pto^.location.register)));
  988. end;
  989. end;
  990. procedure second_bool_to_int(pto,pfrom : ptree;convtyp : tconverttype);
  991. var
  992. oldtruelabel,oldfalselabel,hlabel : plabel;
  993. hregister : tregister;
  994. newsize,
  995. opsize : topsize;
  996. op : tasmop;
  997. begin
  998. oldtruelabel:=truelabel;
  999. oldfalselabel:=falselabel;
  1000. getlabel(truelabel);
  1001. getlabel(falselabel);
  1002. secondpass(pfrom);
  1003. clear_location(pto^.location);
  1004. pto^.location.loc:=LOC_REGISTER;
  1005. del_reference(pfrom^.location.reference);
  1006. case pfrom^.resulttype^.size of
  1007. 1 : begin
  1008. case pto^.resulttype^.size of
  1009. 1 : opsize:=S_B;
  1010. 2 : opsize:=S_BW;
  1011. 4 : opsize:=S_BL;
  1012. end;
  1013. end;
  1014. 2 : begin
  1015. case pto^.resulttype^.size of
  1016. 1 : begin
  1017. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1018. pfrom^.location.register:=reg16toreg8(pfrom^.location.register);
  1019. opsize:=S_B;
  1020. end;
  1021. 2 : opsize:=S_W;
  1022. 4 : opsize:=S_WL;
  1023. end;
  1024. end;
  1025. 4 : begin
  1026. case pto^.resulttype^.size of
  1027. 1 : begin
  1028. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1029. pfrom^.location.register:=reg32toreg8(pfrom^.location.register);
  1030. opsize:=S_B;
  1031. end;
  1032. 2 : begin
  1033. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1034. pfrom^.location.register:=reg32toreg16(pfrom^.location.register);
  1035. opsize:=S_W;
  1036. end;
  1037. 4 : opsize:=S_L;
  1038. end;
  1039. end;
  1040. end;
  1041. if opsize in [S_B,S_W,S_L] then
  1042. op:=A_MOV
  1043. else
  1044. if is_signed(pto^.resulttype) then
  1045. op:=A_MOVSX
  1046. else
  1047. op:=A_MOVZX;
  1048. hregister:=getregister32;
  1049. case pto^.resulttype^.size of
  1050. 1 : begin
  1051. pto^.location.register:=reg32toreg8(hregister);
  1052. newsize:=S_B;
  1053. end;
  1054. 2 : begin
  1055. pto^.location.register:=reg32toreg16(hregister);
  1056. newsize:=S_W;
  1057. end;
  1058. 4 : begin
  1059. pto^.location.register:=hregister;
  1060. newsize:=S_L;
  1061. end;
  1062. else
  1063. internalerror(10060);
  1064. end;
  1065. case pfrom^.location.loc of
  1066. LOC_MEM,
  1067. LOC_REFERENCE : exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  1068. newreference(pfrom^.location.reference),pto^.location.register)));
  1069. LOC_REGISTER,
  1070. LOC_CREGISTER : begin
  1071. { remove things like movb %al,%al }
  1072. if pfrom^.location.register<>pto^.location.register then
  1073. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  1074. pfrom^.location.register,pto^.location.register)));
  1075. end;
  1076. LOC_FLAGS : begin
  1077. hregister:=reg32toreg8(hregister);
  1078. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[pfrom^.location.resflags],S_B,hregister)));
  1079. case pto^.resulttype^.size of
  1080. 2 : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,hregister,pto^.location.register)));
  1081. 4 : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,hregister,pto^.location.register)));
  1082. end;
  1083. end;
  1084. LOC_JUMP : begin
  1085. getlabel(hlabel);
  1086. emitl(A_LABEL,truelabel);
  1087. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,newsize,1,hregister)));
  1088. emitl(A_JMP,hlabel);
  1089. emitl(A_LABEL,falselabel);
  1090. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,newsize,hregister,hregister)));
  1091. emitl(A_LABEL,hlabel);
  1092. end;
  1093. else
  1094. internalerror(10061);
  1095. end;
  1096. freelabel(truelabel);
  1097. freelabel(falselabel);
  1098. truelabel:=oldtruelabel;
  1099. falselabel:=oldfalselabel;
  1100. end;
  1101. procedure second_int_to_bool(pto,pfrom : ptree;convtyp : tconverttype);
  1102. var
  1103. hregister : tregister;
  1104. begin
  1105. clear_location(pto^.location);
  1106. pto^.location.loc:=LOC_REGISTER;
  1107. del_reference(pfrom^.location.reference);
  1108. case pfrom^.location.loc of
  1109. LOC_MEM,LOC_REFERENCE :
  1110. begin
  1111. hregister:=getregister32;
  1112. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1113. newreference(pfrom^.location.reference),hregister)));
  1114. end;
  1115. LOC_REGISTER,LOC_CREGISTER :
  1116. begin
  1117. hregister:=pfrom^.location.register;
  1118. end;
  1119. else
  1120. internalerror(10062);
  1121. end;
  1122. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hregister,hregister)));
  1123. hregister:=reg32toreg8(hregister);
  1124. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[pfrom^.location.resflags],S_B,hregister)));
  1125. case pto^.resulttype^.size of
  1126. 1 : pto^.location.register:=hregister;
  1127. 2 : begin
  1128. pto^.location.register:=reg8toreg16(hregister);
  1129. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,hregister,pto^.location.register)));
  1130. end;
  1131. 4 : begin
  1132. pto^.location.register:=reg8toreg32(hregister);
  1133. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,hregister,pto^.location.register)));
  1134. end;
  1135. else
  1136. internalerror(10064);
  1137. end;
  1138. end;
  1139. procedure second_load_smallset(pto,pfrom : ptree;convtyp : tconverttype);
  1140. var
  1141. href : treference;
  1142. pushedregs : tpushed;
  1143. begin
  1144. href.symbol:=nil;
  1145. pushusedregisters(pushedregs,$ff);
  1146. gettempofsizereference(32,href);
  1147. emitpushreferenceaddr(exprasmlist,pfrom^.location.reference);
  1148. emitpushreferenceaddr(exprasmlist,href);
  1149. emitcall('FPC_SET_LOAD_SMALL',true);
  1150. maybe_loadesi;
  1151. popusedregisters(pushedregs);
  1152. clear_location(pto^.location);
  1153. pto^.location.loc:=LOC_MEM;
  1154. pto^.location.reference:=href;
  1155. end;
  1156. procedure second_ansistring_to_pchar(pto,pfrom : ptree;convtyp : tconverttype);
  1157. var
  1158. l1,l2 : plabel;
  1159. hr : preference;
  1160. begin
  1161. clear_location(pto^.location);
  1162. pto^.location.loc:=LOC_REGISTER;
  1163. getlabel(l1);
  1164. getlabel(l2);
  1165. case pfrom^.location.loc of
  1166. LOC_CREGISTER,LOC_REGISTER:
  1167. exprasmlist^.concat(new(pai386,op_const_reg(A_CMP,S_L,0,
  1168. pfrom^.location.register)));
  1169. LOC_MEM,LOC_REFERENCE:
  1170. begin
  1171. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  1172. newreference(pfrom^.location.reference))));
  1173. del_reference(pfrom^.location.reference);
  1174. pto^.location.register:=getregister32;
  1175. end;
  1176. end;
  1177. emitl(A_JZ,l1);
  1178. if pfrom^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  1179. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  1180. pfrom^.location.reference),
  1181. pto^.location.register)));
  1182. emitl(A_JMP,l2);
  1183. emitl(A_LABEL,l1);
  1184. new(hr);
  1185. reset_reference(hr^);
  1186. hr^.symbol:=stringdup('FPC_EMPTYCHAR');
  1187. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,hr,
  1188. pto^.location.register)));
  1189. emitl(A_LABEL,l2);
  1190. end;
  1191. procedure second_pchar_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  1192. var
  1193. pushed : tpushed;
  1194. begin
  1195. case pstringdef(pto^.resulttype)^.string_typ of
  1196. st_shortstring:
  1197. begin
  1198. pushusedregisters(pushed,$ff);
  1199. stringdispose(pto^.location.reference.symbol);
  1200. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  1201. case pfrom^.location.loc of
  1202. LOC_REGISTER,LOC_CREGISTER:
  1203. begin
  1204. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  1205. ungetregister32(pfrom^.location.register);
  1206. end;
  1207. LOC_REFERENCE,LOC_MEM:
  1208. begin
  1209. emit_push_mem(pfrom^.location.reference);
  1210. del_reference(pfrom^.location.reference);
  1211. end;
  1212. end;
  1213. emitpushreferenceaddr(exprasmlist,pto^.location.reference);
  1214. emitcall('FPC_PCHAR_TO_SHORTSTR',true);
  1215. maybe_loadesi;
  1216. popusedregisters(pushed);
  1217. end;
  1218. st_ansistring:
  1219. begin
  1220. stringdispose(pto^.location.reference.symbol);
  1221. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  1222. ltemptoremove^.concat(new(ptemptodestroy,init(pto^.location.reference,pto^.resulttype)));
  1223. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,0,newreference(pto^.location.reference))));
  1224. case pfrom^.location.loc of
  1225. LOC_REGISTER,LOC_CREGISTER:
  1226. begin
  1227. ungetregister32(pfrom^.location.register);
  1228. pushusedregisters(pushed,$ff);
  1229. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  1230. end;
  1231. LOC_REFERENCE,LOC_MEM:
  1232. begin
  1233. del_reference(pfrom^.location.reference);
  1234. pushusedregisters(pushed,$ff);
  1235. emit_push_mem(pfrom^.location.reference);
  1236. end;
  1237. end;
  1238. emitpushreferenceaddr(exprasmlist,pto^.location.reference);
  1239. emitcall('FPC_PCHAR_TO_ANSISTR',true);
  1240. maybe_loadesi;
  1241. popusedregisters(pushed);
  1242. end;
  1243. else
  1244. begin
  1245. clear_location(pto^.location);
  1246. pto^.location.loc:=LOC_REGISTER;
  1247. internalerror(12121);
  1248. end;
  1249. end;
  1250. end;
  1251. procedure second_nothing(pto,pfrom : ptree;convtyp : tconverttype);
  1252. begin
  1253. end;
  1254. {****************************************************************************
  1255. SecondTypeConv
  1256. ****************************************************************************}
  1257. procedure secondtypeconv(var p : ptree);
  1258. const
  1259. secondconvert : array[tconverttype] of tsecondconvproc = (
  1260. {$ifndef OLDCNV}
  1261. second_nothing, {equal}
  1262. second_nothing, {not_possible}
  1263. second_string_to_string,
  1264. second_char_to_string,
  1265. second_pchar_to_string,
  1266. second_nothing, {cchar_to_pchar}
  1267. second_cstring_to_pchar,
  1268. second_ansistring_to_pchar,
  1269. second_string_to_chararray,
  1270. second_chararray_to_string,
  1271. second_array_to_pointer,
  1272. second_pointer_to_array,
  1273. second_int_to_int,
  1274. second_bool_to_int,
  1275. second_int_to_bool,
  1276. second_real_to_real,
  1277. second_int_to_real,
  1278. second_int_to_fix,
  1279. second_real_to_fix,
  1280. second_fix_to_real,
  1281. second_proc_to_procvar,
  1282. second_nothing, {arrayconstructor_to_set}
  1283. second_load_smallset
  1284. );
  1285. {$else}
  1286. second_nothing,second_nothing,
  1287. second_bigger,second_only_rangecheck,
  1288. second_bigger,second_bigger,second_bigger,
  1289. second_smaller,second_smaller,
  1290. second_smaller,second_string_to_string,
  1291. second_cstring_to_pchar,second_string_to_chararray,
  1292. second_array_to_pointer,second_pointer_to_array,
  1293. second_char_to_string,second_bigger,
  1294. second_bigger,second_bigger,
  1295. second_smaller,second_smaller,
  1296. second_smaller,second_smaller,
  1297. second_bigger,second_smaller,
  1298. second_only_rangecheck,second_bigger,
  1299. second_bigger,second_bigger,
  1300. second_bigger,second_only_rangecheck,
  1301. second_smaller,second_smaller,
  1302. second_smaller,second_smaller,
  1303. second_bool_to_int,second_int_to_bool,
  1304. second_int_to_real,second_real_to_fix,
  1305. second_fix_to_real,second_int_to_fix,second_real_to_real,
  1306. second_chararray_to_string,
  1307. second_proc_to_procvar,
  1308. { is constant char to pchar, is done by firstpass }
  1309. second_nothing,
  1310. second_load_smallset,
  1311. second_ansistring_to_pchar,
  1312. second_pchar_to_string,
  1313. second_nothing);
  1314. {$endif}
  1315. var
  1316. oldrl : plinkedlist;
  1317. begin
  1318. { the ansi string disposing is a little bit hairy: }
  1319. oldrl:=temptoremove;
  1320. temptoremove:=new(plinkedlist,init);
  1321. { the helper routines need access to the release list }
  1322. ltemptoremove:=oldrl;
  1323. if not(assigned(ltemptoremove)) then
  1324. internalerror(18011);
  1325. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1326. { type conversion (FK) }
  1327. { this is necessary, because second_bool_2_int, have to change }
  1328. { true- and false label before calling secondpass }
  1329. if p^.convtyp<>tc_bool_2_int then
  1330. begin
  1331. secondpass(p^.left);
  1332. set_location(p^.location,p^.left^.location);
  1333. if codegenerror then
  1334. exit;
  1335. end;
  1336. { the second argument only is for maybe_range_checking !}
  1337. secondconvert[p^.convtyp](p,p^.left,p^.convtyp);
  1338. { clean up all temp. objects (ansi/widestrings) }
  1339. removetemps(exprasmlist,temptoremove);
  1340. dispose(temptoremove,done);
  1341. temptoremove:=oldrl;
  1342. end;
  1343. {*****************************************************************************
  1344. SecondIs
  1345. *****************************************************************************}
  1346. procedure secondis(var p : ptree);
  1347. var
  1348. pushed : tpushed;
  1349. begin
  1350. { save all used registers }
  1351. pushusedregisters(pushed,$ff);
  1352. secondpass(p^.left);
  1353. clear_location(p^.location);
  1354. p^.location.loc:=LOC_FLAGS;
  1355. p^.location.resflags:=F_NE;
  1356. { push instance to check: }
  1357. case p^.left^.location.loc of
  1358. LOC_REGISTER,LOC_CREGISTER:
  1359. begin
  1360. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1361. S_L,p^.left^.location.register)));
  1362. ungetregister32(p^.left^.location.register);
  1363. end;
  1364. LOC_MEM,LOC_REFERENCE:
  1365. begin
  1366. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1367. S_L,newreference(p^.left^.location.reference))));
  1368. del_reference(p^.left^.location.reference);
  1369. end;
  1370. else internalerror(100);
  1371. end;
  1372. { generate type checking }
  1373. secondpass(p^.right);
  1374. case p^.right^.location.loc of
  1375. LOC_REGISTER,LOC_CREGISTER:
  1376. begin
  1377. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1378. S_L,p^.right^.location.register)));
  1379. ungetregister32(p^.right^.location.register);
  1380. end;
  1381. LOC_MEM,LOC_REFERENCE:
  1382. begin
  1383. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1384. S_L,newreference(p^.right^.location.reference))));
  1385. del_reference(p^.right^.location.reference);
  1386. end;
  1387. else internalerror(100);
  1388. end;
  1389. emitcall('FPC_DO_IS',true);
  1390. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
  1391. popusedregisters(pushed);
  1392. end;
  1393. {*****************************************************************************
  1394. SecondAs
  1395. *****************************************************************************}
  1396. procedure secondas(var p : ptree);
  1397. var
  1398. pushed : tpushed;
  1399. begin
  1400. secondpass(p^.left);
  1401. { save all used registers }
  1402. pushusedregisters(pushed,$ff);
  1403. { push instance to check: }
  1404. case p^.left^.location.loc of
  1405. LOC_REGISTER,LOC_CREGISTER:
  1406. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1407. S_L,p^.left^.location.register)));
  1408. LOC_MEM,LOC_REFERENCE:
  1409. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1410. S_L,newreference(p^.left^.location.reference))));
  1411. else internalerror(100);
  1412. end;
  1413. { we doesn't modifiy the left side, we check only the type }
  1414. set_location(p^.location,p^.left^.location);
  1415. { generate type checking }
  1416. secondpass(p^.right);
  1417. case p^.right^.location.loc of
  1418. LOC_REGISTER,LOC_CREGISTER:
  1419. begin
  1420. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1421. S_L,p^.right^.location.register)));
  1422. ungetregister32(p^.right^.location.register);
  1423. end;
  1424. LOC_MEM,LOC_REFERENCE:
  1425. begin
  1426. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1427. S_L,newreference(p^.right^.location.reference))));
  1428. del_reference(p^.right^.location.reference);
  1429. end;
  1430. else internalerror(100);
  1431. end;
  1432. emitcall('FPC_DO_AS',true);
  1433. { restore register, this restores automatically the }
  1434. { result }
  1435. popusedregisters(pushed);
  1436. end;
  1437. end.
  1438. {
  1439. $Log$
  1440. Revision 1.46 1999-01-27 00:13:53 florian
  1441. * "procedure of object"-stuff fixed
  1442. Revision 1.45 1999/01/21 22:10:36 peter
  1443. * fixed array of const
  1444. * generic platform independent high() support
  1445. Revision 1.44 1999/01/19 10:18:59 florian
  1446. * bug with mul. of dwords fixed, reported by Alexander Stohr
  1447. * some changes to compile with TP
  1448. + small enhancements for the new code generator
  1449. Revision 1.43 1998/12/22 13:10:59 florian
  1450. * memory leaks for ansistring type casts fixed
  1451. Revision 1.42 1998/12/19 00:23:42 florian
  1452. * ansistring memory leaks fixed
  1453. Revision 1.41 1998/11/30 19:48:54 peter
  1454. * some more rangecheck fixes
  1455. Revision 1.40 1998/11/30 09:43:02 pierre
  1456. * some range check bugs fixed (still not working !)
  1457. + added DLL writing support for win32 (also accepts variables)
  1458. + TempAnsi for code that could be used for Temporary ansi strings
  1459. handling
  1460. Revision 1.39 1998/11/29 22:37:30 peter
  1461. * fixed constant ansistring -> pchar
  1462. Revision 1.38 1998/11/29 12:40:19 peter
  1463. * newcnv -> not oldcnv
  1464. Revision 1.37 1998/11/26 21:33:06 peter
  1465. * rangecheck updates
  1466. Revision 1.36 1998/11/26 14:39:11 peter
  1467. * ansistring -> pchar fixed
  1468. * ansistring constants fixed
  1469. * ansistring constants are now written once
  1470. Revision 1.35 1998/11/26 13:10:39 peter
  1471. * new int - int conversion -dNEWCNV
  1472. * some function renamings
  1473. Revision 1.34 1998/11/18 15:44:08 peter
  1474. * VALUEPARA for tp7 compatible value parameters
  1475. Revision 1.33 1998/11/17 00:36:39 peter
  1476. * more ansistring fixes
  1477. Revision 1.32 1998/11/16 15:35:38 peter
  1478. * rename laod/copystring -> load/copyshortstring
  1479. * fixed int-bool cnv bug
  1480. + char-ansistring conversion
  1481. Revision 1.31 1998/11/05 12:02:30 peter
  1482. * released useansistring
  1483. * removed -Sv, its now available in fpc modes
  1484. Revision 1.30 1998/10/27 11:12:45 peter
  1485. * fixed char_to_string which did not set the .loc
  1486. Revision 1.29 1998/10/26 15:18:41 peter
  1487. * fixed fldcw,fstcw for as 2.9.1
  1488. Revision 1.28 1998/10/08 17:17:11 pierre
  1489. * current_module old scanner tagged as invalid if unit is recompiled
  1490. + added ppheap for better info on tracegetmem of heaptrc
  1491. (adds line column and file index)
  1492. * several memory leaks removed ith help of heaptrc !!
  1493. Revision 1.27 1998/10/06 17:16:40 pierre
  1494. * some memory leaks fixed (thanks to Peter for heaptrc !)
  1495. Revision 1.26 1998/10/02 07:20:35 florian
  1496. * range checking in units doesn't work if the units are smartlinked, fixed
  1497. Revision 1.25 1998/09/30 12:14:24 peter
  1498. * fixed boolean(longbool) conversion
  1499. Revision 1.24 1998/09/27 10:16:22 florian
  1500. * type casts pchar<->ansistring fixed
  1501. * ansistring[..] calls does now an unique call
  1502. Revision 1.23 1998/09/23 12:03:51 peter
  1503. * overloading fix for array of const
  1504. Revision 1.22 1998/09/22 15:34:09 peter
  1505. + pchar -> string conversion
  1506. Revision 1.21 1998/09/20 17:46:47 florian
  1507. * some things regarding ansistrings fixed
  1508. Revision 1.20 1998/09/17 09:42:12 peter
  1509. + pass_2 for cg386
  1510. * Message() -> CGMessage() for pass_1/pass_2
  1511. Revision 1.19 1998/09/14 10:43:46 peter
  1512. * all internal RTL functions start with FPC_
  1513. Revision 1.18 1998/09/11 12:29:40 pierre
  1514. * removed explicit range_checking as it is buggy
  1515. Revision 1.17.2.1 1998/09/11 12:08:54 pierre
  1516. * removed explicit range_check was buggy
  1517. Revision 1.17 1998/09/04 08:41:38 peter
  1518. * updated some error CGMessages
  1519. Revision 1.16 1998/09/03 17:39:03 florian
  1520. + better code for type conversation longint/dword to real type
  1521. Revision 1.15 1998/09/03 16:24:50 florian
  1522. * bug of type conversation from dword to real fixed
  1523. * bug fix of Jonas applied
  1524. Revision 1.14 1998/08/28 12:51:39 florian
  1525. + ansistring to pchar type cast fixed
  1526. Revision 1.13 1998/08/28 10:56:56 peter
  1527. * removed warnings
  1528. Revision 1.12 1998/08/14 18:18:38 peter
  1529. + dynamic set contruction
  1530. * smallsets are now working (always longint size)
  1531. Revision 1.11 1998/08/10 23:59:59 peter
  1532. * fixed dup log
  1533. Revision 1.10 1998/08/10 14:49:47 peter
  1534. + localswitches, moduleswitches, globalswitches splitting
  1535. Revision 1.9 1998/08/05 16:00:09 florian
  1536. * some fixes for ansi strings
  1537. Revision 1.8 1998/07/18 22:54:24 florian
  1538. * some ansi/wide/longstring support fixed:
  1539. o parameter passing
  1540. o returning as result from functions
  1541. Revision 1.7 1998/06/12 13:10:34 peter
  1542. * small internalerror nr change
  1543. Revision 1.6 1998/06/12 10:43:12 michael
  1544. Fixed ansistrings : is_ansistring not found
  1545. Revision 1.5 1998/06/08 13:13:30 pierre
  1546. + temporary variables now in temp_gen.pas unit
  1547. because it is processor independent
  1548. * mppc68k.bat modified to undefine i386 and support_mmx
  1549. (which are defaults for i386)
  1550. Revision 1.4 1998/06/05 17:44:10 peter
  1551. * splitted cgi386
  1552. Revision 1.3 1998/06/03 22:48:50 peter
  1553. + wordbool,longbool
  1554. * rename bis,von -> high,low
  1555. * moved some systemunit loading/creating to psystem.pas
  1556. Revision 1.2 1998/06/02 10:52:10 peter
  1557. * fixed second_bool_to_int with bool8bit return
  1558. Revision 1.1 1998/06/01 16:50:18 peter
  1559. + boolean -> ord conversion
  1560. * fixed ord -> boolean conversion
  1561. }