cg386cnv.pas 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730
  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. clear_location(pto^.location);
  976. pto^.location.loc:=LOC_REGISTER;
  977. pto^.location.register:=getregister32;
  978. del_reference(pfrom^.location.reference);
  979. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  980. newreference(pfrom^.location.reference),pto^.location.register)));
  981. end;
  982. procedure second_bool_to_int(pto,pfrom : ptree;convtyp : tconverttype);
  983. var
  984. oldtruelabel,oldfalselabel,hlabel : plabel;
  985. hregister : tregister;
  986. newsize,
  987. opsize : topsize;
  988. op : tasmop;
  989. begin
  990. oldtruelabel:=truelabel;
  991. oldfalselabel:=falselabel;
  992. getlabel(truelabel);
  993. getlabel(falselabel);
  994. secondpass(pfrom);
  995. clear_location(pto^.location);
  996. pto^.location.loc:=LOC_REGISTER;
  997. del_reference(pfrom^.location.reference);
  998. case pfrom^.resulttype^.size of
  999. 1 : begin
  1000. case pto^.resulttype^.size of
  1001. 1 : opsize:=S_B;
  1002. 2 : opsize:=S_BW;
  1003. 4 : opsize:=S_BL;
  1004. end;
  1005. end;
  1006. 2 : begin
  1007. case pto^.resulttype^.size of
  1008. 1 : begin
  1009. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1010. pfrom^.location.register:=reg16toreg8(pfrom^.location.register);
  1011. opsize:=S_B;
  1012. end;
  1013. 2 : opsize:=S_W;
  1014. 4 : opsize:=S_WL;
  1015. end;
  1016. end;
  1017. 4 : begin
  1018. case pto^.resulttype^.size of
  1019. 1 : begin
  1020. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1021. pfrom^.location.register:=reg32toreg8(pfrom^.location.register);
  1022. opsize:=S_B;
  1023. end;
  1024. 2 : begin
  1025. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1026. pfrom^.location.register:=reg32toreg16(pfrom^.location.register);
  1027. opsize:=S_W;
  1028. end;
  1029. 4 : opsize:=S_L;
  1030. end;
  1031. end;
  1032. end;
  1033. if opsize in [S_B,S_W,S_L] then
  1034. op:=A_MOV
  1035. else
  1036. if is_signed(pto^.resulttype) then
  1037. op:=A_MOVSX
  1038. else
  1039. op:=A_MOVZX;
  1040. hregister:=getregister32;
  1041. case pto^.resulttype^.size of
  1042. 1 : begin
  1043. pto^.location.register:=reg32toreg8(hregister);
  1044. newsize:=S_B;
  1045. end;
  1046. 2 : begin
  1047. pto^.location.register:=reg32toreg16(hregister);
  1048. newsize:=S_W;
  1049. end;
  1050. 4 : begin
  1051. pto^.location.register:=hregister;
  1052. newsize:=S_L;
  1053. end;
  1054. else
  1055. internalerror(10060);
  1056. end;
  1057. case pfrom^.location.loc of
  1058. LOC_MEM,
  1059. LOC_REFERENCE : exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  1060. newreference(pfrom^.location.reference),pto^.location.register)));
  1061. LOC_REGISTER,
  1062. LOC_CREGISTER : begin
  1063. { remove things like movb %al,%al }
  1064. if pfrom^.location.register<>pto^.location.register then
  1065. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  1066. pfrom^.location.register,pto^.location.register)));
  1067. end;
  1068. LOC_FLAGS : begin
  1069. hregister:=reg32toreg8(hregister);
  1070. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[pfrom^.location.resflags],S_B,hregister)));
  1071. case pto^.resulttype^.size of
  1072. 2 : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,hregister,pto^.location.register)));
  1073. 4 : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,hregister,pto^.location.register)));
  1074. end;
  1075. end;
  1076. LOC_JUMP : begin
  1077. getlabel(hlabel);
  1078. emitl(A_LABEL,truelabel);
  1079. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,newsize,1,hregister)));
  1080. emitl(A_JMP,hlabel);
  1081. emitl(A_LABEL,falselabel);
  1082. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,newsize,hregister,hregister)));
  1083. emitl(A_LABEL,hlabel);
  1084. end;
  1085. else
  1086. internalerror(10061);
  1087. end;
  1088. freelabel(truelabel);
  1089. freelabel(falselabel);
  1090. truelabel:=oldtruelabel;
  1091. falselabel:=oldfalselabel;
  1092. end;
  1093. procedure second_int_to_bool(pto,pfrom : ptree;convtyp : tconverttype);
  1094. var
  1095. hregister : tregister;
  1096. begin
  1097. clear_location(pto^.location);
  1098. pto^.location.loc:=LOC_REGISTER;
  1099. del_reference(pfrom^.location.reference);
  1100. case pfrom^.location.loc of
  1101. LOC_MEM,LOC_REFERENCE :
  1102. begin
  1103. hregister:=getregister32;
  1104. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1105. newreference(pfrom^.location.reference),hregister)));
  1106. end;
  1107. LOC_REGISTER,LOC_CREGISTER :
  1108. begin
  1109. hregister:=pfrom^.location.register;
  1110. end;
  1111. else
  1112. internalerror(10062);
  1113. end;
  1114. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hregister,hregister)));
  1115. hregister:=reg32toreg8(hregister);
  1116. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[pfrom^.location.resflags],S_B,hregister)));
  1117. case pto^.resulttype^.size of
  1118. 1 : pto^.location.register:=hregister;
  1119. 2 : begin
  1120. pto^.location.register:=reg8toreg16(hregister);
  1121. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,hregister,pto^.location.register)));
  1122. end;
  1123. 4 : begin
  1124. pto^.location.register:=reg8toreg32(hregister);
  1125. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,hregister,pto^.location.register)));
  1126. end;
  1127. else
  1128. internalerror(10064);
  1129. end;
  1130. end;
  1131. procedure second_load_smallset(pto,pfrom : ptree;convtyp : tconverttype);
  1132. var
  1133. href : treference;
  1134. pushedregs : tpushed;
  1135. begin
  1136. href.symbol:=nil;
  1137. pushusedregisters(pushedregs,$ff);
  1138. gettempofsizereference(32,href);
  1139. emitpushreferenceaddr(exprasmlist,pfrom^.location.reference);
  1140. emitpushreferenceaddr(exprasmlist,href);
  1141. emitcall('FPC_SET_LOAD_SMALL',true);
  1142. maybe_loadesi;
  1143. popusedregisters(pushedregs);
  1144. clear_location(pto^.location);
  1145. pto^.location.loc:=LOC_MEM;
  1146. pto^.location.reference:=href;
  1147. end;
  1148. procedure second_ansistring_to_pchar(pto,pfrom : ptree;convtyp : tconverttype);
  1149. var
  1150. l1,l2 : plabel;
  1151. hr : preference;
  1152. begin
  1153. clear_location(pto^.location);
  1154. pto^.location.loc:=LOC_REGISTER;
  1155. getlabel(l1);
  1156. getlabel(l2);
  1157. case pfrom^.location.loc of
  1158. LOC_CREGISTER,LOC_REGISTER:
  1159. exprasmlist^.concat(new(pai386,op_const_reg(A_CMP,S_L,0,
  1160. pfrom^.location.register)));
  1161. LOC_MEM,LOC_REFERENCE:
  1162. begin
  1163. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  1164. newreference(pfrom^.location.reference))));
  1165. del_reference(pfrom^.location.reference);
  1166. pto^.location.register:=getregister32;
  1167. end;
  1168. end;
  1169. emitl(A_JZ,l1);
  1170. if pfrom^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  1171. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  1172. pfrom^.location.reference),
  1173. pto^.location.register)));
  1174. emitl(A_JMP,l2);
  1175. emitl(A_LABEL,l1);
  1176. new(hr);
  1177. reset_reference(hr^);
  1178. hr^.symbol:=stringdup('FPC_EMPTYCHAR');
  1179. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,hr,
  1180. pto^.location.register)));
  1181. emitl(A_LABEL,l2);
  1182. end;
  1183. procedure second_pchar_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  1184. var
  1185. pushed : tpushed;
  1186. begin
  1187. case pstringdef(pto^.resulttype)^.string_typ of
  1188. st_shortstring:
  1189. begin
  1190. pushusedregisters(pushed,$ff);
  1191. stringdispose(pto^.location.reference.symbol);
  1192. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  1193. case pfrom^.location.loc of
  1194. LOC_REGISTER,LOC_CREGISTER:
  1195. begin
  1196. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  1197. ungetregister32(pfrom^.location.register);
  1198. end;
  1199. LOC_REFERENCE,LOC_MEM:
  1200. begin
  1201. emit_push_mem(pfrom^.location.reference);
  1202. del_reference(pfrom^.location.reference);
  1203. end;
  1204. end;
  1205. emitpushreferenceaddr(exprasmlist,pto^.location.reference);
  1206. emitcall('FPC_PCHAR_TO_SHORTSTR',true);
  1207. maybe_loadesi;
  1208. popusedregisters(pushed);
  1209. end;
  1210. st_ansistring:
  1211. begin
  1212. stringdispose(pto^.location.reference.symbol);
  1213. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  1214. ltemptoremove^.concat(new(ptemptodestroy,init(pto^.location.reference,pto^.resulttype)));
  1215. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,0,newreference(pto^.location.reference))));
  1216. case pfrom^.location.loc of
  1217. LOC_REGISTER,LOC_CREGISTER:
  1218. begin
  1219. ungetregister32(pfrom^.location.register);
  1220. pushusedregisters(pushed,$ff);
  1221. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  1222. end;
  1223. LOC_REFERENCE,LOC_MEM:
  1224. begin
  1225. del_reference(pfrom^.location.reference);
  1226. pushusedregisters(pushed,$ff);
  1227. emit_push_mem(pfrom^.location.reference);
  1228. end;
  1229. end;
  1230. emitpushreferenceaddr(exprasmlist,pto^.location.reference);
  1231. emitcall('FPC_PCHAR_TO_ANSISTR',true);
  1232. maybe_loadesi;
  1233. popusedregisters(pushed);
  1234. end;
  1235. else
  1236. begin
  1237. clear_location(pto^.location);
  1238. pto^.location.loc:=LOC_REGISTER;
  1239. internalerror(12121);
  1240. end;
  1241. end;
  1242. end;
  1243. procedure second_nothing(pto,pfrom : ptree;convtyp : tconverttype);
  1244. begin
  1245. end;
  1246. {****************************************************************************
  1247. SecondTypeConv
  1248. ****************************************************************************}
  1249. procedure secondtypeconv(var p : ptree);
  1250. const
  1251. secondconvert : array[tconverttype] of tsecondconvproc = (
  1252. {$ifndef OLDCNV}
  1253. second_nothing, {equal}
  1254. second_nothing, {not_possible}
  1255. second_string_to_string,
  1256. second_char_to_string,
  1257. second_pchar_to_string,
  1258. second_nothing, {cchar_to_pchar}
  1259. second_cstring_to_pchar,
  1260. second_ansistring_to_pchar,
  1261. second_string_to_chararray,
  1262. second_chararray_to_string,
  1263. second_array_to_pointer,
  1264. second_pointer_to_array,
  1265. second_int_to_int,
  1266. second_bool_to_int,
  1267. second_int_to_bool,
  1268. second_real_to_real,
  1269. second_int_to_real,
  1270. second_int_to_fix,
  1271. second_real_to_fix,
  1272. second_fix_to_real,
  1273. second_proc_to_procvar,
  1274. second_nothing, {arrayconstructor_to_set}
  1275. second_load_smallset
  1276. );
  1277. {$else}
  1278. second_nothing,second_nothing,
  1279. second_bigger,second_only_rangecheck,
  1280. second_bigger,second_bigger,second_bigger,
  1281. second_smaller,second_smaller,
  1282. second_smaller,second_string_to_string,
  1283. second_cstring_to_pchar,second_string_to_chararray,
  1284. second_array_to_pointer,second_pointer_to_array,
  1285. second_char_to_string,second_bigger,
  1286. second_bigger,second_bigger,
  1287. second_smaller,second_smaller,
  1288. second_smaller,second_smaller,
  1289. second_bigger,second_smaller,
  1290. second_only_rangecheck,second_bigger,
  1291. second_bigger,second_bigger,
  1292. second_bigger,second_only_rangecheck,
  1293. second_smaller,second_smaller,
  1294. second_smaller,second_smaller,
  1295. second_bool_to_int,second_int_to_bool,
  1296. second_int_to_real,second_real_to_fix,
  1297. second_fix_to_real,second_int_to_fix,second_real_to_real,
  1298. second_chararray_to_string,
  1299. second_proc_to_procvar,
  1300. { is constant char to pchar, is done by firstpass }
  1301. second_nothing,
  1302. second_load_smallset,
  1303. second_ansistring_to_pchar,
  1304. second_pchar_to_string,
  1305. second_nothing);
  1306. {$endif}
  1307. var
  1308. oldrl : plinkedlist;
  1309. begin
  1310. { the ansi string disposing is a little bit hairy: }
  1311. oldrl:=temptoremove;
  1312. temptoremove:=new(plinkedlist,init);
  1313. { the helper routines need access to the release list }
  1314. ltemptoremove:=oldrl;
  1315. if not(assigned(ltemptoremove)) then
  1316. internalerror(18011);
  1317. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1318. { type conversion (FK) }
  1319. { this is necessary, because second_bool_2_int, have to change }
  1320. { true- and false label before calling secondpass }
  1321. if p^.convtyp<>tc_bool_2_int then
  1322. begin
  1323. secondpass(p^.left);
  1324. set_location(p^.location,p^.left^.location);
  1325. if codegenerror then
  1326. exit;
  1327. end;
  1328. { the second argument only is for maybe_range_checking !}
  1329. secondconvert[p^.convtyp](p,p^.left,p^.convtyp);
  1330. { clean up all temp. objects (ansi/widestrings) }
  1331. removetemps(exprasmlist,temptoremove);
  1332. dispose(temptoremove,done);
  1333. temptoremove:=oldrl;
  1334. end;
  1335. {*****************************************************************************
  1336. SecondIs
  1337. *****************************************************************************}
  1338. procedure secondis(var p : ptree);
  1339. var
  1340. pushed : tpushed;
  1341. begin
  1342. { save all used registers }
  1343. pushusedregisters(pushed,$ff);
  1344. secondpass(p^.left);
  1345. clear_location(p^.location);
  1346. p^.location.loc:=LOC_FLAGS;
  1347. p^.location.resflags:=F_NE;
  1348. { push instance to check: }
  1349. case p^.left^.location.loc of
  1350. LOC_REGISTER,LOC_CREGISTER:
  1351. begin
  1352. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1353. S_L,p^.left^.location.register)));
  1354. ungetregister32(p^.left^.location.register);
  1355. end;
  1356. LOC_MEM,LOC_REFERENCE:
  1357. begin
  1358. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1359. S_L,newreference(p^.left^.location.reference))));
  1360. del_reference(p^.left^.location.reference);
  1361. end;
  1362. else internalerror(100);
  1363. end;
  1364. { generate type checking }
  1365. secondpass(p^.right);
  1366. case p^.right^.location.loc of
  1367. LOC_REGISTER,LOC_CREGISTER:
  1368. begin
  1369. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1370. S_L,p^.right^.location.register)));
  1371. ungetregister32(p^.right^.location.register);
  1372. end;
  1373. LOC_MEM,LOC_REFERENCE:
  1374. begin
  1375. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1376. S_L,newreference(p^.right^.location.reference))));
  1377. del_reference(p^.right^.location.reference);
  1378. end;
  1379. else internalerror(100);
  1380. end;
  1381. emitcall('FPC_DO_IS',true);
  1382. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
  1383. popusedregisters(pushed);
  1384. end;
  1385. {*****************************************************************************
  1386. SecondAs
  1387. *****************************************************************************}
  1388. procedure secondas(var p : ptree);
  1389. var
  1390. pushed : tpushed;
  1391. begin
  1392. secondpass(p^.left);
  1393. { save all used registers }
  1394. pushusedregisters(pushed,$ff);
  1395. { push instance to check: }
  1396. case p^.left^.location.loc of
  1397. LOC_REGISTER,LOC_CREGISTER:
  1398. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1399. S_L,p^.left^.location.register)));
  1400. LOC_MEM,LOC_REFERENCE:
  1401. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1402. S_L,newreference(p^.left^.location.reference))));
  1403. else internalerror(100);
  1404. end;
  1405. { we doesn't modifiy the left side, we check only the type }
  1406. set_location(p^.location,p^.left^.location);
  1407. { generate type checking }
  1408. secondpass(p^.right);
  1409. case p^.right^.location.loc of
  1410. LOC_REGISTER,LOC_CREGISTER:
  1411. begin
  1412. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1413. S_L,p^.right^.location.register)));
  1414. ungetregister32(p^.right^.location.register);
  1415. end;
  1416. LOC_MEM,LOC_REFERENCE:
  1417. begin
  1418. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1419. S_L,newreference(p^.right^.location.reference))));
  1420. del_reference(p^.right^.location.reference);
  1421. end;
  1422. else internalerror(100);
  1423. end;
  1424. emitcall('FPC_DO_AS',true);
  1425. { restore register, this restores automatically the }
  1426. { result }
  1427. popusedregisters(pushed);
  1428. end;
  1429. end.
  1430. {
  1431. $Log$
  1432. Revision 1.45 1999-01-21 22:10:36 peter
  1433. * fixed array of const
  1434. * generic platform independent high() support
  1435. Revision 1.44 1999/01/19 10:18:59 florian
  1436. * bug with mul. of dwords fixed, reported by Alexander Stohr
  1437. * some changes to compile with TP
  1438. + small enhancements for the new code generator
  1439. Revision 1.43 1998/12/22 13:10:59 florian
  1440. * memory leaks for ansistring type casts fixed
  1441. Revision 1.42 1998/12/19 00:23:42 florian
  1442. * ansistring memory leaks fixed
  1443. Revision 1.41 1998/11/30 19:48:54 peter
  1444. * some more rangecheck fixes
  1445. Revision 1.40 1998/11/30 09:43:02 pierre
  1446. * some range check bugs fixed (still not working !)
  1447. + added DLL writing support for win32 (also accepts variables)
  1448. + TempAnsi for code that could be used for Temporary ansi strings
  1449. handling
  1450. Revision 1.39 1998/11/29 22:37:30 peter
  1451. * fixed constant ansistring -> pchar
  1452. Revision 1.38 1998/11/29 12:40:19 peter
  1453. * newcnv -> not oldcnv
  1454. Revision 1.37 1998/11/26 21:33:06 peter
  1455. * rangecheck updates
  1456. Revision 1.36 1998/11/26 14:39:11 peter
  1457. * ansistring -> pchar fixed
  1458. * ansistring constants fixed
  1459. * ansistring constants are now written once
  1460. Revision 1.35 1998/11/26 13:10:39 peter
  1461. * new int - int conversion -dNEWCNV
  1462. * some function renamings
  1463. Revision 1.34 1998/11/18 15:44:08 peter
  1464. * VALUEPARA for tp7 compatible value parameters
  1465. Revision 1.33 1998/11/17 00:36:39 peter
  1466. * more ansistring fixes
  1467. Revision 1.32 1998/11/16 15:35:38 peter
  1468. * rename laod/copystring -> load/copyshortstring
  1469. * fixed int-bool cnv bug
  1470. + char-ansistring conversion
  1471. Revision 1.31 1998/11/05 12:02:30 peter
  1472. * released useansistring
  1473. * removed -Sv, its now available in fpc modes
  1474. Revision 1.30 1998/10/27 11:12:45 peter
  1475. * fixed char_to_string which did not set the .loc
  1476. Revision 1.29 1998/10/26 15:18:41 peter
  1477. * fixed fldcw,fstcw for as 2.9.1
  1478. Revision 1.28 1998/10/08 17:17:11 pierre
  1479. * current_module old scanner tagged as invalid if unit is recompiled
  1480. + added ppheap for better info on tracegetmem of heaptrc
  1481. (adds line column and file index)
  1482. * several memory leaks removed ith help of heaptrc !!
  1483. Revision 1.27 1998/10/06 17:16:40 pierre
  1484. * some memory leaks fixed (thanks to Peter for heaptrc !)
  1485. Revision 1.26 1998/10/02 07:20:35 florian
  1486. * range checking in units doesn't work if the units are smartlinked, fixed
  1487. Revision 1.25 1998/09/30 12:14:24 peter
  1488. * fixed boolean(longbool) conversion
  1489. Revision 1.24 1998/09/27 10:16:22 florian
  1490. * type casts pchar<->ansistring fixed
  1491. * ansistring[..] calls does now an unique call
  1492. Revision 1.23 1998/09/23 12:03:51 peter
  1493. * overloading fix for array of const
  1494. Revision 1.22 1998/09/22 15:34:09 peter
  1495. + pchar -> string conversion
  1496. Revision 1.21 1998/09/20 17:46:47 florian
  1497. * some things regarding ansistrings fixed
  1498. Revision 1.20 1998/09/17 09:42:12 peter
  1499. + pass_2 for cg386
  1500. * Message() -> CGMessage() for pass_1/pass_2
  1501. Revision 1.19 1998/09/14 10:43:46 peter
  1502. * all internal RTL functions start with FPC_
  1503. Revision 1.18 1998/09/11 12:29:40 pierre
  1504. * removed explicit range_checking as it is buggy
  1505. Revision 1.17.2.1 1998/09/11 12:08:54 pierre
  1506. * removed explicit range_check was buggy
  1507. Revision 1.17 1998/09/04 08:41:38 peter
  1508. * updated some error CGMessages
  1509. Revision 1.16 1998/09/03 17:39:03 florian
  1510. + better code for type conversation longint/dword to real type
  1511. Revision 1.15 1998/09/03 16:24:50 florian
  1512. * bug of type conversation from dword to real fixed
  1513. * bug fix of Jonas applied
  1514. Revision 1.14 1998/08/28 12:51:39 florian
  1515. + ansistring to pchar type cast fixed
  1516. Revision 1.13 1998/08/28 10:56:56 peter
  1517. * removed warnings
  1518. Revision 1.12 1998/08/14 18:18:38 peter
  1519. + dynamic set contruction
  1520. * smallsets are now working (always longint size)
  1521. Revision 1.11 1998/08/10 23:59:59 peter
  1522. * fixed dup log
  1523. Revision 1.10 1998/08/10 14:49:47 peter
  1524. + localswitches, moduleswitches, globalswitches splitting
  1525. Revision 1.9 1998/08/05 16:00:09 florian
  1526. * some fixes for ansi strings
  1527. Revision 1.8 1998/07/18 22:54:24 florian
  1528. * some ansi/wide/longstring support fixed:
  1529. o parameter passing
  1530. o returning as result from functions
  1531. Revision 1.7 1998/06/12 13:10:34 peter
  1532. * small internalerror nr change
  1533. Revision 1.6 1998/06/12 10:43:12 michael
  1534. Fixed ansistrings : is_ansistring not found
  1535. Revision 1.5 1998/06/08 13:13:30 pierre
  1536. + temporary variables now in temp_gen.pas unit
  1537. because it is processor independent
  1538. * mppc68k.bat modified to undefine i386 and support_mmx
  1539. (which are defaults for i386)
  1540. Revision 1.4 1998/06/05 17:44:10 peter
  1541. * splitted cgi386
  1542. Revision 1.3 1998/06/03 22:48:50 peter
  1543. + wordbool,longbool
  1544. * rename bis,von -> high,low
  1545. * moved some systemunit loading/creating to psystem.pas
  1546. Revision 1.2 1998/06/02 10:52:10 peter
  1547. * fixed second_bool_to_int with bool8bit return
  1548. Revision 1.1 1998/06/01 16:50:18 peter
  1549. + boolean -> ord conversion
  1550. * fixed ord -> boolean conversion
  1551. }