n386inl.pas 37 KB

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