n386inl.pas 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 inline 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. unit n386inl;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,ninl;
  23. type
  24. ti386inlinenode = class(tinlinenode)
  25. procedure pass_2;override;
  26. end;
  27. implementation
  28. uses
  29. globtype,systems,
  30. cutils,verbose,globals,fmodule,
  31. symconst,symbase,symtype,symdef,symsym,aasm,types,
  32. cgbase,temp_gen,pass_1,pass_2,
  33. cpubase,
  34. nbas,ncon,ncal,ncnv,nld,
  35. cga,tgcpu,n386util;
  36. {*****************************************************************************
  37. Helpers
  38. *****************************************************************************}
  39. { reverts the parameter list }
  40. var nb_para : longint;
  41. function reversparameter(p : tnode) : tnode;
  42. var
  43. hp1,hp2 : tnode;
  44. begin
  45. hp1:=nil;
  46. nb_para := 0;
  47. while assigned(p) do
  48. begin
  49. { pull out }
  50. hp2:=p;
  51. p:=tbinarynode(p).right;
  52. inc(nb_para);
  53. { pull in }
  54. tbinarynode(hp2).right:=hp1;
  55. hp1:=hp2;
  56. end;
  57. reversparameter:=hp1;
  58. end;
  59. {*****************************************************************************
  60. TI386INLINENODE
  61. *****************************************************************************}
  62. procedure ti386inlinenode.pass_2;
  63. const
  64. {tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
  65. { float_name: array[tfloattype] of string[8]=
  66. ('S32REAL','S64REAL','S80REAL','S64BIT','F16BIT','F32BIT'); }
  67. incdecop:array[in_inc_x..in_dec_x] of tasmop=(A_INC,A_DEC);
  68. addsubop:array[in_inc_x..in_dec_x] of tasmop=(A_ADD,A_SUB);
  69. var
  70. aktfile : treference;
  71. ft : tfiletyp;
  72. opsize : topsize;
  73. op,
  74. asmop : tasmop;
  75. pushed : tpushed;
  76. {inc/dec}
  77. addconstant : boolean;
  78. addvalue : longint;
  79. hp : tnode;
  80. var
  81. r : preference;
  82. //hp : tcallparanode;
  83. hp2 : tstringconstnode;
  84. dummycoll : tparaitem;
  85. l : longint;
  86. ispushed : boolean;
  87. hregister : tregister;
  88. lengthlab,
  89. otlabel,oflabel{,l1} : tasmlabel;
  90. oldpushedparasize : longint;
  91. def : tdef;
  92. hr,hr2 : treference;
  93. begin
  94. { save & reset pushedparasize }
  95. oldpushedparasize:=pushedparasize;
  96. pushedparasize:=0;
  97. case inlinenumber of
  98. in_assert_x_y:
  99. begin
  100. { the node should be removed in the firstpass }
  101. if not (cs_do_assertion in aktlocalswitches) then
  102. internalerror(7123458);
  103. otlabel:=truelabel;
  104. oflabel:=falselabel;
  105. getlabel(truelabel);
  106. getlabel(falselabel);
  107. secondpass(tcallparanode(left).left);
  108. maketojumpbool(tcallparanode(left).left);
  109. emitlab(falselabel);
  110. { erroraddr }
  111. emit_reg(A_PUSH,S_L,R_EBP);
  112. { lineno }
  113. emit_const(A_PUSH,S_L,aktfilepos.line);
  114. { filename string }
  115. hp2:=cstringconstnode.createstr(current_module.sourcefiles.get_file_name(aktfilepos.fileindex),st_shortstring);
  116. firstpass(hp2);
  117. secondpass(hp2);
  118. if codegenerror then
  119. exit;
  120. emitpushreferenceaddr(hp2.location.reference);
  121. hp2.free;
  122. { push msg }
  123. secondpass(tcallparanode(tcallparanode(left).right).left);
  124. emitpushreferenceaddr(tcallparanode(tcallparanode(left).right).left.location.reference);
  125. { call }
  126. emitcall('FPC_ASSERT');
  127. emitlab(truelabel);
  128. truelabel:=otlabel;
  129. falselabel:=oflabel;
  130. end;
  131. in_lo_word,
  132. in_hi_word :
  133. begin
  134. secondpass(left);
  135. location.loc:=LOC_REGISTER;
  136. if left.location.loc<>LOC_REGISTER then
  137. begin
  138. if left.location.loc=LOC_CREGISTER then
  139. begin
  140. location.register:=reg32toreg16(getregister32);
  141. emit_reg_reg(A_MOV,S_W,left.location.register,
  142. location.register);
  143. end
  144. else
  145. begin
  146. del_reference(left.location.reference);
  147. location.register:=reg32toreg16(getregister32);
  148. emit_ref_reg(A_MOV,S_W,newreference(left.location.reference),
  149. location.register);
  150. end;
  151. end
  152. else location.register:=left.location.register;
  153. if inlinenumber=in_hi_word then
  154. emit_const_reg(A_SHR,S_W,8,location.register);
  155. location.register:=reg16toreg8(location.register);
  156. end;
  157. in_sizeof_x,
  158. in_typeof_x :
  159. begin
  160. { for both cases load vmt }
  161. if left.nodetype=typen then
  162. begin
  163. location.register:=getregister32;
  164. emit_sym_ofs_reg(A_MOV,
  165. S_L,newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),0,
  166. location.register);
  167. end
  168. else
  169. begin
  170. secondpass(left);
  171. del_reference(left.location.reference);
  172. location.loc:=LOC_REGISTER;
  173. location.register:=getregister32;
  174. { load VMT pointer }
  175. inc(left.location.reference.offset,
  176. tobjectdef(left.resulttype.def).vmt_offset);
  177. emit_ref_reg(A_MOV,S_L,
  178. newreference(left.location.reference),
  179. location.register);
  180. end;
  181. { in sizeof load size }
  182. if inlinenumber=in_sizeof_x then
  183. begin
  184. new(r);
  185. reset_reference(r^);
  186. r^.base:=location.register;
  187. emit_ref_reg(A_MOV,S_L,r,
  188. location.register);
  189. end;
  190. end;
  191. in_lo_long,
  192. in_hi_long :
  193. begin
  194. secondpass(left);
  195. location.loc:=LOC_REGISTER;
  196. if left.location.loc<>LOC_REGISTER then
  197. begin
  198. if left.location.loc=LOC_CREGISTER then
  199. begin
  200. location.register:=getregister32;
  201. emit_reg_reg(A_MOV,S_L,left.location.register,
  202. location.register);
  203. end
  204. else
  205. begin
  206. del_reference(left.location.reference);
  207. location.register:=getregister32;
  208. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  209. location.register);
  210. end;
  211. end
  212. else location.register:=left.location.register;
  213. if inlinenumber=in_hi_long then
  214. emit_const_reg(A_SHR,S_L,16,location.register);
  215. location.register:=reg32toreg16(location.register);
  216. end;
  217. in_lo_qword,
  218. in_hi_qword:
  219. begin
  220. secondpass(left);
  221. location.loc:=LOC_REGISTER;
  222. case left.location.loc of
  223. LOC_CREGISTER:
  224. begin
  225. location.register:=getregister32;
  226. if inlinenumber=in_hi_qword then
  227. emit_reg_reg(A_MOV,S_L,left.location.registerhigh,
  228. location.register)
  229. else
  230. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  231. location.register)
  232. end;
  233. LOC_MEM,LOC_REFERENCE:
  234. begin
  235. del_reference(left.location.reference);
  236. location.register:=getregister32;
  237. r:=newreference(left.location.reference);
  238. if inlinenumber=in_hi_qword then
  239. inc(r^.offset,4);
  240. emit_ref_reg(A_MOV,S_L,
  241. r,location.register);
  242. end;
  243. LOC_REGISTER:
  244. begin
  245. if inlinenumber=in_hi_qword then
  246. begin
  247. location.register:=left.location.registerhigh;
  248. ungetregister32(left.location.registerlow);
  249. end
  250. else
  251. begin
  252. location.register:=left.location.registerlow;
  253. ungetregister32(left.location.registerhigh);
  254. end;
  255. end;
  256. end;
  257. end;
  258. in_length_x :
  259. begin
  260. secondpass(left);
  261. set_location(location,left.location);
  262. { length in ansi strings is at offset -8 }
  263. if is_ansistring(left.resulttype.def) or
  264. is_widestring(left.resulttype.def) then
  265. begin
  266. if left.location.loc<>LOC_REGISTER then
  267. begin
  268. del_location(left.location);
  269. hregister:=getregister32;
  270. emit_mov_loc_reg(left.location,hregister);
  271. end
  272. else
  273. hregister:=left.location.register;
  274. reset_reference(hr);
  275. hr.base:=hregister;
  276. hr.offset:=-8;
  277. getlabel(lengthlab);
  278. emit_reg_reg(A_OR,S_L,hregister,hregister);
  279. emitjmp(C_Z,lengthlab);
  280. emit_ref_reg(A_MOV,S_L,newreference(hr),hregister);
  281. emitlab(lengthlab);
  282. location.loc:=LOC_REGISTER;
  283. location.register:=hregister;
  284. end;
  285. end;
  286. in_pred_x,
  287. in_succ_x:
  288. begin
  289. secondpass(left);
  290. if not (cs_check_overflow in aktlocalswitches) then
  291. if inlinenumber=in_pred_x then
  292. asmop:=A_DEC
  293. else
  294. asmop:=A_INC
  295. else
  296. if inlinenumber=in_pred_x then
  297. asmop:=A_SUB
  298. else
  299. asmop:=A_ADD;
  300. case resulttype.def.size of
  301. 8 : opsize:=S_L;
  302. 4 : opsize:=S_L;
  303. 2 : opsize:=S_W;
  304. 1 : opsize:=S_B;
  305. else
  306. internalerror(10080);
  307. end;
  308. location.loc:=LOC_REGISTER;
  309. if resulttype.def.size=8 then
  310. begin
  311. if left.location.loc<>LOC_REGISTER then
  312. begin
  313. if left.location.loc=LOC_CREGISTER then
  314. begin
  315. location.registerlow:=getregister32;
  316. location.registerhigh:=getregister32;
  317. emit_reg_reg(A_MOV,opsize,left.location.registerlow,
  318. location.registerlow);
  319. emit_reg_reg(A_MOV,opsize,left.location.registerhigh,
  320. location.registerhigh);
  321. end
  322. else
  323. begin
  324. del_reference(left.location.reference);
  325. location.registerlow:=getregister32;
  326. location.registerhigh:=getregister32;
  327. emit_ref_reg(A_MOV,opsize,newreference(left.location.reference),
  328. location.registerlow);
  329. r:=newreference(left.location.reference);
  330. inc(r^.offset,4);
  331. emit_ref_reg(A_MOV,opsize,r,
  332. location.registerhigh);
  333. end;
  334. end
  335. else
  336. begin
  337. location.registerhigh:=left.location.registerhigh;
  338. location.registerlow:=left.location.registerlow;
  339. end;
  340. if inlinenumber=in_succ_x then
  341. begin
  342. emit_const_reg(A_ADD,opsize,1,
  343. location.registerlow);
  344. emit_const_reg(A_ADC,opsize,0,
  345. location.registerhigh);
  346. end
  347. else
  348. begin
  349. emit_const_reg(A_SUB,opsize,1,
  350. location.registerlow);
  351. emit_const_reg(A_SBB,opsize,0,
  352. location.registerhigh);
  353. end;
  354. end
  355. else
  356. begin
  357. if left.location.loc<>LOC_REGISTER then
  358. begin
  359. { first, we've to release the source location ... }
  360. if left.location.loc in [LOC_MEM,LOC_REFERENCE] then
  361. del_reference(left.location.reference);
  362. location.register:=getregister32;
  363. if (resulttype.def.size=2) then
  364. location.register:=reg32toreg16(location.register);
  365. if (resulttype.def.size=1) then
  366. location.register:=reg32toreg8(location.register);
  367. if left.location.loc=LOC_CREGISTER then
  368. emit_reg_reg(A_MOV,opsize,left.location.register,
  369. location.register)
  370. else
  371. if left.location.loc=LOC_FLAGS then
  372. emit_flag2reg(left.location.resflags,location.register)
  373. else
  374. emit_ref_reg(A_MOV,opsize,newreference(left.location.reference),
  375. location.register);
  376. end
  377. else location.register:=left.location.register;
  378. if not (cs_check_overflow in aktlocalswitches) then
  379. emit_reg(asmop,opsize,
  380. location.register)
  381. else
  382. emit_const_reg(asmop,opsize,1,
  383. location.register);
  384. end;
  385. emitoverflowcheck(self);
  386. emitrangecheck(self,resulttype.def);
  387. end;
  388. in_dec_x,
  389. in_inc_x :
  390. begin
  391. { set defaults }
  392. addvalue:=1;
  393. addconstant:=true;
  394. { load first parameter, must be a reference }
  395. secondpass(tcallparanode(left).left);
  396. case tcallparanode(left).left.resulttype.def.deftype of
  397. orddef,
  398. enumdef : begin
  399. case tcallparanode(left).left.resulttype.def.size of
  400. 1 : opsize:=S_B;
  401. 2 : opsize:=S_W;
  402. 4 : opsize:=S_L;
  403. 8 : opsize:=S_L;
  404. end;
  405. end;
  406. pointerdef : begin
  407. opsize:=S_L;
  408. if is_void(tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def) then
  409. addvalue:=1
  410. else
  411. addvalue:=tpointerdef(tcallparanode(left).left.resulttype.def).pointertype.def.size;
  412. end;
  413. else
  414. internalerror(10081);
  415. end;
  416. { second argument specified?, must be a s32bit in register }
  417. if assigned(tcallparanode(left).right) then
  418. begin
  419. ispushed:=maybe_push(tcallparanode(tcallparanode(left).right).left.registers32,
  420. tcallparanode(left).left,false);
  421. secondpass(tcallparanode(tcallparanode(left).right).left);
  422. if ispushed then
  423. restore(tcallparanode(left).left,false);
  424. { when constant, just multiply the addvalue }
  425. if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
  426. addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
  427. else
  428. begin
  429. case tcallparanode(tcallparanode(left).right).left.location.loc of
  430. LOC_REGISTER,
  431. LOC_CREGISTER : hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
  432. LOC_MEM,
  433. LOC_REFERENCE : begin
  434. del_reference(tcallparanode(tcallparanode(left).right).left.location.reference);
  435. hregister:=getregister32;
  436. emit_ref_reg(A_MOV,S_L,
  437. newreference(tcallparanode(tcallparanode(left).right).left.location.reference),hregister);
  438. end;
  439. else
  440. internalerror(10082);
  441. end;
  442. { insert multiply with addvalue if its >1 }
  443. if addvalue>1 then
  444. emit_const_reg(A_IMUL,opsize,
  445. addvalue,hregister);
  446. addconstant:=false;
  447. end;
  448. end;
  449. { write the add instruction }
  450. if addconstant then
  451. begin
  452. if (addvalue=1) and not(cs_check_overflow in aktlocalswitches) then
  453. begin
  454. if tcallparanode(left).left.location.loc=LOC_CREGISTER then
  455. emit_reg(incdecop[inlinenumber],opsize,
  456. tcallparanode(left).left.location.register)
  457. else
  458. emit_ref(incdecop[inlinenumber],opsize,
  459. newreference(tcallparanode(left).left.location.reference))
  460. end
  461. else
  462. begin
  463. if tcallparanode(left).left.location.loc=LOC_CREGISTER then
  464. emit_const_reg(addsubop[inlinenumber],opsize,
  465. addvalue,tcallparanode(left).left.location.register)
  466. else
  467. emit_const_ref(addsubop[inlinenumber],opsize,
  468. addvalue,newreference(tcallparanode(left).left.location.reference));
  469. end
  470. end
  471. else
  472. begin
  473. { BUG HERE : detected with nasm :
  474. hregister is allways 32 bit
  475. it should be converted to 16 or 8 bit depending on op_size PM }
  476. { still not perfect :
  477. if hregister is already a 16 bit reg ?? PM }
  478. { makeregXX is the solution (FK) }
  479. case opsize of
  480. S_B : hregister:=makereg8(hregister);
  481. S_W : hregister:=makereg16(hregister);
  482. end;
  483. if tcallparanode(left).left.location.loc=LOC_CREGISTER then
  484. emit_reg_reg(addsubop[inlinenumber],opsize,
  485. hregister,tcallparanode(left).left.location.register)
  486. else
  487. emit_reg_ref(addsubop[inlinenumber],opsize,
  488. hregister,newreference(tcallparanode(left).left.location.reference));
  489. case opsize of
  490. S_B : hregister:=reg8toreg32(hregister);
  491. S_W : hregister:=reg16toreg32(hregister);
  492. end;
  493. ungetregister32(hregister);
  494. end;
  495. emitoverflowcheck(tcallparanode(left).left);
  496. emitrangecheck(tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
  497. end;
  498. in_typeinfo_x:
  499. begin
  500. location.register:=getregister32;
  501. new(r);
  502. reset_reference(r^);
  503. r^.symbol:=tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(fullrtti);
  504. emit_ref_reg(A_LEA,S_L,r,location.register);
  505. end;
  506. in_finalize_x:
  507. begin
  508. pushusedregisters(pushed,$ff);
  509. { if a count is passed, push size, typeinfo and count }
  510. if assigned(tcallparanode(left).right) then
  511. begin
  512. secondpass(tcallparanode(tcallparanode(left).right).left);
  513. push_int(tcallparanode(left).left.resulttype.def.size);
  514. if codegenerror then
  515. exit;
  516. emit_push_loc(tcallparanode(tcallparanode(left).right).left.location);
  517. end;
  518. { generate a reference }
  519. reset_reference(hr);
  520. hr.symbol:=tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(initrtti);
  521. emitpushreferenceaddr(hr);
  522. { data to finalize }
  523. secondpass(tcallparanode(left).left);
  524. if codegenerror then
  525. exit;
  526. emitpushreferenceaddr(tcallparanode(left).left.location.reference);
  527. saveregvars($ff);
  528. if assigned(tcallparanode(left).right) then
  529. emitcall('FPC_FINALIZEARRAY')
  530. else
  531. emitcall('FPC_FINALIZE');
  532. popusedregisters(pushed);
  533. end;
  534. in_assigned_x :
  535. begin
  536. secondpass(tcallparanode(left).left);
  537. location.loc:=LOC_FLAGS;
  538. if (tcallparanode(left).left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  539. begin
  540. emit_reg_reg(A_OR,S_L,
  541. tcallparanode(left).left.location.register,
  542. tcallparanode(left).left.location.register);
  543. ungetregister32(tcallparanode(left).left.location.register);
  544. end
  545. else
  546. begin
  547. emit_const_ref(A_CMP,S_L,0,
  548. newreference(tcallparanode(left).left.location.reference));
  549. del_reference(tcallparanode(left).left.location.reference);
  550. end;
  551. location.resflags:=F_NE;
  552. end;
  553. in_reset_typedfile,in_rewrite_typedfile :
  554. begin
  555. { should be removed in pass_1 (JM) }
  556. internalerror(200108132);
  557. end;
  558. in_setlength_x:
  559. begin
  560. pushusedregisters(pushed,$ff);
  561. l:=0;
  562. { push dimensions }
  563. hp:=left;
  564. while assigned(tcallparanode(hp).right) do
  565. begin
  566. inc(l);
  567. hp:=tcallparanode(hp).right;
  568. end;
  569. def:=tcallparanode(hp).left.resulttype.def;
  570. hp:=left;
  571. if is_dynamic_array(def) then
  572. begin
  573. { get temp. space }
  574. gettempofsizereference(l*4,hr);
  575. { keep data start }
  576. hr2:=hr;
  577. { copy dimensions }
  578. hp:=left;
  579. while assigned(tcallparanode(hp).right) do
  580. begin
  581. secondpass(tcallparanode(hp).left);
  582. emit_mov_loc_ref(tcallparanode(hp).left.location,hr,
  583. S_L,true);
  584. inc(hr.offset,4);
  585. hp:=tcallparanode(hp).right;
  586. end;
  587. end
  588. else
  589. begin
  590. secondpass(tcallparanode(hp).left);
  591. emit_push_loc(tcallparanode(hp).left.location);
  592. hp:=tcallparanode(hp).right;
  593. end;
  594. { handle shortstrings separately since the hightree must be }
  595. { pushed too (JM) }
  596. if not(is_dynamic_array(def)) and
  597. (tstringdef(def).string_typ = st_shortstring) then
  598. begin
  599. dummycoll:=TParaItem.Create;
  600. dummycoll.paratyp:=vs_var;
  601. dummycoll.paratype:=openshortstringtype;
  602. tcallparanode(hp).secondcallparan(dummycoll,false,false,false,0,0);
  603. dummycoll.free;
  604. if codegenerror then
  605. exit;
  606. end
  607. else secondpass(tcallparanode(hp).left);
  608. if is_dynamic_array(def) then
  609. begin
  610. emitpushreferenceaddr(hr2);
  611. push_int(l);
  612. reset_reference(hr2);
  613. hr2.symbol:=tstoreddef(def).get_rtti_label(initrtti);
  614. emitpushreferenceaddr(hr2);
  615. emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
  616. saveregvars($ff);
  617. emitcall('FPC_DYNARR_SETLENGTH');
  618. ungetiftemp(hr);
  619. end
  620. else
  621. { must be string }
  622. begin
  623. case tstringdef(def).string_typ of
  624. st_widestring:
  625. begin
  626. emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
  627. saveregvars($ff);
  628. emitcall('FPC_WIDESTR_SETLENGTH');
  629. end;
  630. st_ansistring:
  631. begin
  632. emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
  633. saveregvars($ff);
  634. emitcall('FPC_ANSISTR_SETLENGTH');
  635. end;
  636. st_shortstring:
  637. begin
  638. saveregvars($ff);
  639. emitcall('FPC_SHORTSTR_SETLENGTH');
  640. end;
  641. end;
  642. end;
  643. popusedregisters(pushed);
  644. end;
  645. in_read_x,
  646. in_readln_x,
  647. in_write_x,
  648. in_writeln_x :
  649. { should be removed in the resulttype pass already (JM) }
  650. internalerror(200108162);
  651. in_str_x_string :
  652. begin
  653. { should be removed in det_resulttype (JM) }
  654. internalerror(200108131);
  655. end;
  656. in_val_x :
  657. Begin
  658. { should be removed in det_resulttype (JM) }
  659. internalerror(200108241);
  660. End;
  661. in_include_x_y,
  662. in_exclude_x_y:
  663. begin
  664. secondpass(tcallparanode(left).left);
  665. if tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn then
  666. begin
  667. { calculate bit position }
  668. l:=1 shl (tordconstnode(tcallparanode(tcallparanode(left).right).left).value mod 32);
  669. { determine operator }
  670. if inlinenumber=in_include_x_y then
  671. asmop:=A_OR
  672. else
  673. begin
  674. asmop:=A_AND;
  675. l:=not(l);
  676. end;
  677. if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
  678. begin
  679. inc(tcallparanode(left).left.location.reference.offset,
  680. (tordconstnode(tcallparanode(tcallparanode(left).right).left).value div 32)*4);
  681. emit_const_ref(asmop,S_L,
  682. l,newreference(tcallparanode(left).left.location.reference));
  683. del_reference(tcallparanode(left).left.location.reference);
  684. end
  685. else
  686. { LOC_CREGISTER }
  687. begin
  688. secondpass(tcallparanode(left).left);
  689. emit_const_reg(asmop,S_L,
  690. l,tcallparanode(left).left.location.register);
  691. end;
  692. end
  693. else
  694. begin
  695. { generate code for the element to set }
  696. ispushed:=maybe_push(tcallparanode(tcallparanode(left).right).left.registers32,
  697. tcallparanode(left).left,false);
  698. secondpass(tcallparanode(tcallparanode(left).right).left);
  699. if ispushed then
  700. restore(tcallparanode(left).left,false);
  701. { determine asm operator }
  702. if inlinenumber=in_include_x_y then
  703. asmop:=A_BTS
  704. else
  705. asmop:=A_BTR;
  706. if tsetdef(left.resulttype.def).settype=smallset then
  707. begin
  708. if tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  709. { we don't need a mod 32 because this is done automatically }
  710. { by the bts instruction. For proper checking we would }
  711. { need a cmp and jmp, but this should be done by the }
  712. { type cast code which does range checking if necessary (FK) }
  713. hregister:=makereg32(tcallparanode(tcallparanode(left).right).left.location.register)
  714. else
  715. begin
  716. getexplicitregister32(R_EDI);
  717. hregister:=R_EDI;
  718. opsize:=def2def_opsize(
  719. tcallparanode(tcallparanode(left).right).left.resulttype.def,u32bittype.def);
  720. if opsize in [S_B,S_W,S_L] then
  721. op:=A_MOV
  722. else
  723. op:=A_MOVZX;
  724. emit_ref_reg(op,opsize,
  725. newreference(
  726. tcallparanode(tcallparanode(left).right).left.location.reference),R_EDI);
  727. end;
  728. if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
  729. emit_reg_ref(asmop,S_L,hregister,
  730. newreference(tcallparanode(left).left.location.reference))
  731. else
  732. emit_reg_reg(asmop,S_L,hregister,
  733. tcallparanode(left).left.location.register);
  734. if hregister = R_EDI then
  735. ungetregister32(R_EDI);
  736. end
  737. else
  738. begin
  739. pushsetelement(tcallparanode(tcallparanode(left).right).left);
  740. { normset is allways a ref }
  741. emitpushreferenceaddr(tcallparanode(left).left.location.reference);
  742. if inlinenumber=in_include_x_y then
  743. emitcall('FPC_SET_SET_BYTE')
  744. else
  745. emitcall('FPC_SET_UNSET_BYTE');
  746. {CGMessage(cg_e_include_not_implemented);}
  747. end;
  748. end;
  749. end;
  750. in_pi:
  751. begin
  752. emit_none(A_FLDPI,S_NO);
  753. inc(fpuvaroffset);
  754. end;
  755. in_sin_extended,
  756. in_arctan_extended,
  757. in_abs_extended,
  758. in_sqr_extended,
  759. in_sqrt_extended,
  760. in_ln_extended,
  761. in_cos_extended:
  762. begin
  763. secondpass(left);
  764. case left.location.loc of
  765. LOC_FPU:
  766. ;
  767. LOC_CFPUREGISTER:
  768. begin
  769. emit_reg(A_FLD,S_NO,
  770. correct_fpuregister(left.location.register,fpuvaroffset));
  771. inc(fpuvaroffset);
  772. end;
  773. LOC_REFERENCE,LOC_MEM:
  774. begin
  775. floatload(tfloatdef(left.resulttype.def).typ,left.location.reference);
  776. del_reference(left.location.reference);
  777. end
  778. else
  779. internalerror(309991);
  780. end;
  781. case inlinenumber of
  782. in_sin_extended,
  783. in_cos_extended:
  784. begin
  785. if inlinenumber=in_sin_extended then
  786. emit_none(A_FSIN,S_NO)
  787. else
  788. emit_none(A_FCOS,S_NO);
  789. {
  790. getlabel(l1);
  791. emit_reg(A_FNSTSW,S_NO,R_AX);
  792. emit_none(A_SAHF,S_NO);
  793. emitjmp(C_NP,l1);
  794. emit_reg(A_FSTP,S_NO,R_ST0);
  795. emit_none(A_FLDZ,S_NO);
  796. emitlab(l1);
  797. }
  798. end;
  799. in_arctan_extended:
  800. begin
  801. emit_none(A_FLD1,S_NO);
  802. emit_none(A_FPATAN,S_NO);
  803. end;
  804. in_abs_extended:
  805. emit_none(A_FABS,S_NO);
  806. in_sqr_extended:
  807. begin
  808. (* emit_reg(A_FLD,S_NO,R_ST0);
  809. { emit_none(A_FMULP,S_NO); nasm does not accept this PM }
  810. emit_reg_reg(A_FMULP,S_NO,R_ST0,R_ST1);
  811. can be shorten to *)
  812. emit_reg_reg(A_FMUL,S_NO,R_ST0,R_ST0);
  813. end;
  814. in_sqrt_extended:
  815. emit_none(A_FSQRT,S_NO);
  816. in_ln_extended:
  817. begin
  818. emit_none(A_FLDLN2,S_NO);
  819. emit_none(A_FXCH,S_NO);
  820. emit_none(A_FYL2X,S_NO);
  821. end;
  822. end;
  823. end;
  824. {$ifdef SUPPORT_MMX}
  825. in_mmx_pcmpeqb..in_mmx_pcmpgtw:
  826. begin
  827. if left.location.loc=LOC_REGISTER then
  828. begin
  829. {!!!!!!!}
  830. end
  831. else if tcallparanode(left).left.location.loc=LOC_REGISTER then
  832. begin
  833. {!!!!!!!}
  834. end
  835. else
  836. begin
  837. {!!!!!!!}
  838. end;
  839. end;
  840. {$endif SUPPORT_MMX}
  841. else internalerror(9);
  842. end;
  843. { reset pushedparasize }
  844. pushedparasize:=oldpushedparasize;
  845. end;
  846. begin
  847. cinlinenode:=ti386inlinenode;
  848. end.
  849. {
  850. $Log$
  851. Revision 1.23 2001-08-30 20:13:57 peter
  852. * rtti/init table updates
  853. * rttisym for reusable global rtti/init info
  854. * support published for interfaces
  855. Revision 1.22 2001/08/28 13:24:47 jonas
  856. + compilerproc implementation of most string-related type conversions
  857. - removed all code from the compiler which has been replaced by
  858. compilerproc implementations (using {$ifdef hascompilerproc} is not
  859. necessary in the compiler)
  860. Revision 1.21 2001/08/26 13:36:58 florian
  861. * some cg reorganisation
  862. * some PPC updates
  863. Revision 1.20 2001/08/24 12:33:54 jonas
  864. * fixed big bug in handle_str that caused it to (almost) always call
  865. fpc_<stringtype>_longint
  866. * fixed small bug in handle_read_write that caused wrong warnigns about
  867. uninitialized vars with read(ln)
  868. + handle_val (processor independent val() handling)
  869. Revision 1.19 2001/08/23 14:28:36 jonas
  870. + tempcreate/ref/delete nodes (allows the use of temps in the
  871. resulttype and first pass)
  872. * made handling of read(ln)/write(ln) processor independent
  873. * moved processor independent handling for str and reset/rewrite-typed
  874. from firstpass to resulttype pass
  875. * changed names of helpers in text.inc to be generic for use as
  876. compilerprocs + added "iocheck" directive for most of them
  877. * reading of ordinals is done by procedures instead of functions
  878. because otherwise FPC_IOCHECK overwrote the result before it could
  879. be stored elsewhere (range checking still works)
  880. * compilerprocs can now be used in the system unit before they are
  881. implemented
  882. * added note to errore.msg that booleans can't be read using read/readln
  883. Revision 1.18 2001/08/13 15:39:52 jonas
  884. * made in_reset_typedfile/in_rewrite_typedfile handling processor
  885. independent
  886. Revision 1.17 2001/08/13 12:41:57 jonas
  887. * made code for str(x,y) completely processor independent
  888. Revision 1.16 2001/07/10 18:01:08 peter
  889. * internal length for ansistring and widestrings
  890. Revision 1.15 2001/07/08 21:00:18 peter
  891. * various widestring updates, it works now mostly without charset
  892. mapping supported
  893. Revision 1.14 2001/04/13 01:22:19 peter
  894. * symtable change to classes
  895. * range check generation and errors fixed, make cycle DEBUG=1 works
  896. * memory leaks fixed
  897. Revision 1.13 2001/04/02 21:20:37 peter
  898. * resulttype rewrite
  899. Revision 1.12 2001/03/13 11:52:48 jonas
  900. * fixed some memory leaks
  901. Revision 1.11 2000/12/25 00:07:33 peter
  902. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  903. tlinkedlist objects)
  904. Revision 1.10 2000/12/09 22:51:37 florian
  905. * helper name of val for qword fixed
  906. Revision 1.9 2000/12/07 17:19:46 jonas
  907. * new constant handling: from now on, hex constants >$7fffffff are
  908. parsed as unsigned constants (otherwise, $80000000 got sign extended
  909. and became $ffffffff80000000), all constants in the longint range
  910. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  911. are cardinals and the rest are int64's.
  912. * added lots of longint typecast to prevent range check errors in the
  913. compiler and rtl
  914. * type casts of symbolic ordinal constants are now preserved
  915. * fixed bug where the original resulttype.def wasn't restored correctly
  916. after doing a 64bit rangecheck
  917. Revision 1.8 2000/12/05 11:44:33 jonas
  918. + new integer regvar handling, should be much more efficient
  919. Revision 1.7 2000/11/29 00:30:47 florian
  920. * unused units removed from uses clause
  921. * some changes for widestrings
  922. Revision 1.6 2000/11/12 23:24:15 florian
  923. * interfaces are basically running
  924. Revision 1.5 2000/11/09 17:46:56 florian
  925. * System.TypeInfo fixed
  926. + System.Finalize implemented
  927. + some new keywords for interface support added
  928. Revision 1.4 2000/10/31 22:02:56 peter
  929. * symtable splitted, no real code changes
  930. Revision 1.3 2000/10/26 14:15:07 jonas
  931. * fixed setlength for shortstrings
  932. Revision 1.2 2000/10/21 18:16:13 florian
  933. * a lot of changes:
  934. - basic dyn. array support
  935. - basic C++ support
  936. - some work for interfaces done
  937. ....
  938. Revision 1.1 2000/10/15 09:33:31 peter
  939. * moved n386*.pas to i386/ cpu_target dir
  940. Revision 1.2 2000/10/15 09:08:58 peter
  941. * use System for the systemunit instead of target dependent
  942. Revision 1.1 2000/10/14 10:14:49 peter
  943. * moehrendorf oct 2000 rewrite
  944. }