n386inl.pas 37 KB

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