n386inl.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  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 tcallparanode(tcallparanode(left).right).left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  707. { we don't need a mod 32 because this is done automatically }
  708. { by the bts instruction. For proper checking we would }
  709. { note: bts doesn't do any mod'ing, that's why we can also use }
  710. { it for normalsets! (JM) }
  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 = 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. end;
  738. in_pi:
  739. begin
  740. emit_none(A_FLDPI,S_NO);
  741. inc(fpuvaroffset);
  742. end;
  743. in_sin_extended,
  744. in_arctan_extended,
  745. in_abs_extended,
  746. in_sqr_extended,
  747. in_sqrt_extended,
  748. in_ln_extended,
  749. in_cos_extended:
  750. begin
  751. secondpass(left);
  752. case left.location.loc of
  753. LOC_FPU:
  754. ;
  755. LOC_CFPUREGISTER:
  756. begin
  757. emit_reg(A_FLD,S_NO,
  758. correct_fpuregister(left.location.register,fpuvaroffset));
  759. inc(fpuvaroffset);
  760. end;
  761. LOC_REFERENCE,LOC_MEM:
  762. begin
  763. floatload(tfloatdef(left.resulttype.def).typ,left.location.reference);
  764. del_reference(left.location.reference);
  765. end
  766. else
  767. internalerror(309991);
  768. end;
  769. case inlinenumber of
  770. in_sin_extended,
  771. in_cos_extended:
  772. begin
  773. if inlinenumber=in_sin_extended then
  774. emit_none(A_FSIN,S_NO)
  775. else
  776. emit_none(A_FCOS,S_NO);
  777. {
  778. getlabel(l1);
  779. emit_reg(A_FNSTSW,S_NO,R_AX);
  780. emit_none(A_SAHF,S_NO);
  781. emitjmp(C_NP,l1);
  782. emit_reg(A_FSTP,S_NO,R_ST0);
  783. emit_none(A_FLDZ,S_NO);
  784. emitlab(l1);
  785. }
  786. end;
  787. in_arctan_extended:
  788. begin
  789. emit_none(A_FLD1,S_NO);
  790. emit_none(A_FPATAN,S_NO);
  791. end;
  792. in_abs_extended:
  793. emit_none(A_FABS,S_NO);
  794. in_sqr_extended:
  795. begin
  796. (* emit_reg(A_FLD,S_NO,R_ST0);
  797. { emit_none(A_FMULP,S_NO); nasm does not accept this PM }
  798. emit_reg_reg(A_FMULP,S_NO,R_ST0,R_ST1);
  799. can be shorten to *)
  800. emit_reg_reg(A_FMUL,S_NO,R_ST0,R_ST0);
  801. end;
  802. in_sqrt_extended:
  803. emit_none(A_FSQRT,S_NO);
  804. in_ln_extended:
  805. begin
  806. emit_none(A_FLDLN2,S_NO);
  807. emit_none(A_FXCH,S_NO);
  808. emit_none(A_FYL2X,S_NO);
  809. end;
  810. end;
  811. end;
  812. {$ifdef SUPPORT_MMX}
  813. in_mmx_pcmpeqb..in_mmx_pcmpgtw:
  814. begin
  815. if left.location.loc=LOC_REGISTER then
  816. begin
  817. {!!!!!!!}
  818. end
  819. else if tcallparanode(left).left.location.loc=LOC_REGISTER then
  820. begin
  821. {!!!!!!!}
  822. end
  823. else
  824. begin
  825. {!!!!!!!}
  826. end;
  827. end;
  828. {$endif SUPPORT_MMX}
  829. else internalerror(9);
  830. end;
  831. { reset pushedparasize }
  832. pushedparasize:=oldpushedparasize;
  833. end;
  834. begin
  835. cinlinenode:=ti386inlinenode;
  836. end.
  837. {
  838. $Log$
  839. Revision 1.24 2001-09-04 14:32:45 jonas
  840. * simplified det_resulttype code for include/exclude
  841. * include/exclude doesn't use any helpers anymore in the i386 secondpass
  842. Revision 1.23 2001/08/30 20:13:57 peter
  843. * rtti/init table updates
  844. * rttisym for reusable global rtti/init info
  845. * support published for interfaces
  846. Revision 1.22 2001/08/28 13:24:47 jonas
  847. + compilerproc implementation of most string-related type conversions
  848. - removed all code from the compiler which has been replaced by
  849. compilerproc implementations (using {$ifdef hascompilerproc} is not
  850. necessary in the compiler)
  851. Revision 1.21 2001/08/26 13:36:58 florian
  852. * some cg reorganisation
  853. * some PPC updates
  854. Revision 1.20 2001/08/24 12:33:54 jonas
  855. * fixed big bug in handle_str that caused it to (almost) always call
  856. fpc_<stringtype>_longint
  857. * fixed small bug in handle_read_write that caused wrong warnigns about
  858. uninitialized vars with read(ln)
  859. + handle_val (processor independent val() handling)
  860. Revision 1.19 2001/08/23 14:28:36 jonas
  861. + tempcreate/ref/delete nodes (allows the use of temps in the
  862. resulttype and first pass)
  863. * made handling of read(ln)/write(ln) processor independent
  864. * moved processor independent handling for str and reset/rewrite-typed
  865. from firstpass to resulttype pass
  866. * changed names of helpers in text.inc to be generic for use as
  867. compilerprocs + added "iocheck" directive for most of them
  868. * reading of ordinals is done by procedures instead of functions
  869. because otherwise FPC_IOCHECK overwrote the result before it could
  870. be stored elsewhere (range checking still works)
  871. * compilerprocs can now be used in the system unit before they are
  872. implemented
  873. * added note to errore.msg that booleans can't be read using read/readln
  874. Revision 1.18 2001/08/13 15:39:52 jonas
  875. * made in_reset_typedfile/in_rewrite_typedfile handling processor
  876. independent
  877. Revision 1.17 2001/08/13 12:41:57 jonas
  878. * made code for str(x,y) completely processor independent
  879. Revision 1.16 2001/07/10 18:01:08 peter
  880. * internal length for ansistring and widestrings
  881. Revision 1.15 2001/07/08 21:00:18 peter
  882. * various widestring updates, it works now mostly without charset
  883. mapping supported
  884. Revision 1.14 2001/04/13 01:22:19 peter
  885. * symtable change to classes
  886. * range check generation and errors fixed, make cycle DEBUG=1 works
  887. * memory leaks fixed
  888. Revision 1.13 2001/04/02 21:20:37 peter
  889. * resulttype rewrite
  890. Revision 1.12 2001/03/13 11:52:48 jonas
  891. * fixed some memory leaks
  892. Revision 1.11 2000/12/25 00:07:33 peter
  893. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  894. tlinkedlist objects)
  895. Revision 1.10 2000/12/09 22:51:37 florian
  896. * helper name of val for qword fixed
  897. Revision 1.9 2000/12/07 17:19:46 jonas
  898. * new constant handling: from now on, hex constants >$7fffffff are
  899. parsed as unsigned constants (otherwise, $80000000 got sign extended
  900. and became $ffffffff80000000), all constants in the longint range
  901. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  902. are cardinals and the rest are int64's.
  903. * added lots of longint typecast to prevent range check errors in the
  904. compiler and rtl
  905. * type casts of symbolic ordinal constants are now preserved
  906. * fixed bug where the original resulttype.def wasn't restored correctly
  907. after doing a 64bit rangecheck
  908. Revision 1.8 2000/12/05 11:44:33 jonas
  909. + new integer regvar handling, should be much more efficient
  910. Revision 1.7 2000/11/29 00:30:47 florian
  911. * unused units removed from uses clause
  912. * some changes for widestrings
  913. Revision 1.6 2000/11/12 23:24:15 florian
  914. * interfaces are basically running
  915. Revision 1.5 2000/11/09 17:46:56 florian
  916. * System.TypeInfo fixed
  917. + System.Finalize implemented
  918. + some new keywords for interface support added
  919. Revision 1.4 2000/10/31 22:02:56 peter
  920. * symtable splitted, no real code changes
  921. Revision 1.3 2000/10/26 14:15:07 jonas
  922. * fixed setlength for shortstrings
  923. Revision 1.2 2000/10/21 18:16:13 florian
  924. * a lot of changes:
  925. - basic dyn. array support
  926. - basic C++ support
  927. - some work for interfaces done
  928. ....
  929. Revision 1.1 2000/10/15 09:33:31 peter
  930. * moved n386*.pas to i386/ cpu_target dir
  931. Revision 1.2 2000/10/15 09:08:58 peter
  932. * use System for the systemunit instead of target dependent
  933. Revision 1.1 2000/10/14 10:14:49 peter
  934. * moehrendorf oct 2000 rewrite
  935. }