n386inl.pas 41 KB

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