n386inl.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  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. cgobj,cga,tgcpu,n386util,ncgutil;
  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:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  198. location.registerhigh:=getregisterint;
  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:=getregisterint;
  208. location.registerhigh:=getregisterint;
  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:=getregisterint;
  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. cg.g_rangecheck(exprasmlist,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:=getregisterint;
  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. cg.g_rangecheck(exprasmlist,tcallparanode(left).left,tcallparanode(left).left.resulttype.def);
  379. end;
  380. in_typeinfo_x:
  381. begin
  382. location.register:=getregisterint;
  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.31 2001-12-30 17:24:46 jonas
  705. * range checking is now processor independent (part in cgobj, part in cg64f32) and should work correctly again (it needed some changes after the changes of the low and high of tordef's to int64) * maketojumpbool() is now processor independent (in ncgutil) * getregister32 is now called getregisterint
  706. Revision 1.30 2001/12/10 14:34:04 jonas
  707. * fixed type conversions from dynamic arrays to open arrays
  708. Revision 1.29 2001/12/04 15:59:03 jonas
  709. * converted lo/hi to processor independent code, generated code is the
  710. same as before (when turning on the optimizer)
  711. Revision 1.28 2001/12/02 16:19:17 jonas
  712. * less unnecessary regvar loading with if-statements
  713. Revision 1.26 2001/09/28 20:38:51 jonas
  714. * fixed big bug in my previous changes (the arguent for bts/btr is always
  715. a 32 bit register, but it wasn't cleared properly if the value was only
  716. an 8 bit one)
  717. Revision 1.25 2001/09/27 13:03:18 jonas
  718. * fixed bug reported by sg about self not being restored after calling
  719. setlength
  720. Revision 1.24 2001/09/04 14:32:45 jonas
  721. * simplified det_resulttype code for include/exclude
  722. * include/exclude doesn't use any helpers anymore in the i386 secondpass
  723. Revision 1.23 2001/08/30 20:13:57 peter
  724. * rtti/init table updates
  725. * rttisym for reusable global rtti/init info
  726. * support published for interfaces
  727. Revision 1.22 2001/08/28 13:24:47 jonas
  728. + compilerproc implementation of most string-related type conversions
  729. - removed all code from the compiler which has been replaced by
  730. compilerproc implementations (using ($ifdef hascompilerproc) is not
  731. necessary in the compiler)
  732. Revision 1.21 2001/08/26 13:36:58 florian
  733. * some cg reorganisation
  734. * some PPC updates
  735. Revision 1.20 2001/08/24 12:33:54 jonas
  736. * fixed big bug in handle_str that caused it to (almost) always call
  737. fpc_<stringtype>_longint
  738. * fixed small bug in handle_read_write that caused wrong warnigns about
  739. uninitialized vars with read(ln)
  740. + handle_val (processor independent val() handling)
  741. Revision 1.19 2001/08/23 14:28:36 jonas
  742. + tempcreate/ref/delete nodes (allows the use of temps in the
  743. resulttype and first pass)
  744. * made handling of read(ln)/write(ln) processor independent
  745. * moved processor independent handling for str and reset/rewrite-typed
  746. from firstpass to resulttype pass
  747. * changed names of helpers in text.inc to be generic for use as
  748. compilerprocs + added "iocheck" directive for most of them
  749. * reading of ordinals is done by procedures instead of functions
  750. because otherwise FPC_IOCHECK overwrote the result before it could
  751. be stored elsewhere (range checking still works)
  752. * compilerprocs can now be used in the system unit before they are
  753. implemented
  754. * added note to errore.msg that booleans can't be read using read/readln
  755. Revision 1.18 2001/08/13 15:39:52 jonas
  756. * made in_reset_typedfile/in_rewrite_typedfile handling processor
  757. independent
  758. Revision 1.17 2001/08/13 12:41:57 jonas
  759. * made code for str(x,y) completely processor independent
  760. Revision 1.16 2001/07/10 18:01:08 peter
  761. * internal length for ansistring and widestrings
  762. Revision 1.15 2001/07/08 21:00:18 peter
  763. * various widestring updates, it works now mostly without charset
  764. mapping supported
  765. Revision 1.14 2001/04/13 01:22:19 peter
  766. * symtable change to classes
  767. * range check generation and errors fixed, make cycle DEBUG=1 works
  768. * memory leaks fixed
  769. Revision 1.13 2001/04/02 21:20:37 peter
  770. * resulttype rewrite
  771. Revision 1.12 2001/03/13 11:52:48 jonas
  772. * fixed some memory leaks
  773. Revision 1.11 2000/12/25 00:07:33 peter
  774. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  775. tlinkedlist objects)
  776. Revision 1.10 2000/12/09 22:51:37 florian
  777. * helper name of val for qword fixed
  778. Revision 1.9 2000/12/07 17:19:46 jonas
  779. * new constant handling: from now on, hex constants >$7fffffff are
  780. parsed as unsigned constants (otherwise, $80000000 got sign extended
  781. and became $ffffffff80000000), all constants in the longint range
  782. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  783. are cardinals and the rest are int64's.
  784. * added lots of longint typecast to prevent range check errors in the
  785. compiler and rtl
  786. * type casts of symbolic ordinal constants are now preserved
  787. * fixed bug where the original resulttype.def wasn't restored correctly
  788. after doing a 64bit rangecheck
  789. Revision 1.8 2000/12/05 11:44:33 jonas
  790. + new integer regvar handling, should be much more efficient
  791. Revision 1.7 2000/11/29 00:30:47 florian
  792. * unused units removed from uses clause
  793. * some changes for widestrings
  794. Revision 1.6 2000/11/12 23:24:15 florian
  795. * interfaces are basically running
  796. Revision 1.5 2000/11/09 17:46:56 florian
  797. * System.TypeInfo fixed
  798. + System.Finalize implemented
  799. + some new keywords for interface support added
  800. Revision 1.4 2000/10/31 22:02:56 peter
  801. * symtable splitted, no real code changes
  802. Revision 1.3 2000/10/26 14:15:07 jonas
  803. * fixed setlength for shortstrings
  804. Revision 1.2 2000/10/21 18:16:13 florian
  805. * a lot of changes:
  806. - basic dyn. array support
  807. - basic C++ support
  808. - some work for interfaces done
  809. ....
  810. Revision 1.1 2000/10/15 09:33:31 peter
  811. * moved n386*.pas to i386/ cpu_target dir
  812. Revision 1.2 2000/10/15 09:08:58 peter
  813. * use System for the systemunit instead of target dependent
  814. Revision 1.1 2000/10/14 10:14:49 peter
  815. * moehrendorf oct 2000 rewrite
  816. }