n386mem.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for in memory related 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 n386mem;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,nmem,ncgmem;
  23. type
  24. ti386newnode = class(tnewnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386addrnode = class(tcgaddrnode)
  28. procedure pass_2;override;
  29. end;
  30. ti386simplenewdisposenode = class(tsimplenewdisposenode)
  31. procedure pass_2;override;
  32. end;
  33. ti386derefnode = class(tcgderefnode)
  34. procedure pass_2;override;
  35. end;
  36. ti386vecnode = class(tvecnode)
  37. procedure pass_2;override;
  38. end;
  39. implementation
  40. uses
  41. {$ifdef delphi}
  42. sysutils,
  43. {$endif}
  44. globtype,systems,
  45. cutils,verbose,globals,
  46. symconst,symtype,symdef,symsym,symtable,aasm,types,
  47. cgbase,pass_2,
  48. pass_1,nld,ncon,nadd,
  49. cpubase,cpuasm,
  50. cgobj,cga,tgobj,n386util,rgobj;
  51. {*****************************************************************************
  52. TI386NEWNODE
  53. *****************************************************************************}
  54. procedure ti386newnode.pass_2;
  55. var
  56. pushed : tpushedsaved;
  57. regstopush: tregisterset;
  58. r : preference;
  59. begin
  60. if assigned(left) then
  61. begin
  62. secondpass(left);
  63. location.register:=left.location.register;
  64. end
  65. else
  66. begin
  67. regstopush := all_registers;
  68. remove_non_regvars_from_loc(location,regstopush);
  69. rg.saveusedregisters(exprasmlist,pushed,regstopush);
  70. tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,location.reference);
  71. { determines the size of the mem block }
  72. push_int(tpointerdef(resulttype.def).pointertype.def.size);
  73. emit_push_lea_loc(location,false);
  74. rg.saveregvars(exprasmlist,all_registers);
  75. emitcall('FPC_GETMEM');
  76. if tpointerdef(resulttype.def).pointertype.def.needs_inittable then
  77. begin
  78. new(r);
  79. reset_reference(r^);
  80. r^.symbol:=tstoreddef(tpointerdef(resulttype.def).pointertype.def).get_rtti_label(initrtti);
  81. emitpushreferenceaddr(r^);
  82. dispose(r);
  83. { push pointer we just allocated, we need to initialize the
  84. data located at that pointer not the pointer self (PFV) }
  85. emit_push_loc(location);
  86. emitcall('FPC_INITIALIZE');
  87. end;
  88. rg.restoreusedregisters(exprasmlist,pushed);
  89. { may be load ESI }
  90. maybe_loadself;
  91. end;
  92. if codegenerror then
  93. exit;
  94. end;
  95. {*****************************************************************************
  96. TI386ADDRNODE
  97. *****************************************************************************}
  98. procedure ti386addrnode.pass_2;
  99. begin
  100. inherited pass_2;
  101. { for use of other segments }
  102. if left.location.reference.segment<>R_NO then
  103. location.segment:=left.location.reference.segment;
  104. end;
  105. {*****************************************************************************
  106. TI386SIMPLENEWDISPOSENODE
  107. *****************************************************************************}
  108. procedure ti386simplenewdisposenode.pass_2;
  109. var
  110. regstopush: tregisterset;
  111. pushed : tpushedsaved;
  112. lefttemp: treference;
  113. r : preference;
  114. left_needs_initfinal: boolean;
  115. procedure saveleft;
  116. begin
  117. tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,
  118. lefttemp);
  119. cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,lefttemp);
  120. rg.del_location(exprasmlist,left.location);
  121. end;
  122. begin
  123. secondpass(left);
  124. if codegenerror then
  125. exit;
  126. left_needs_initfinal :=
  127. tpointerdef(left.resulttype.def).pointertype.def.needs_inittable;
  128. regstopush := all_registers;
  129. remove_non_regvars_from_loc(left.location,regstopush);
  130. rg.saveusedregisters(exprasmlist,pushed,regstopush);
  131. rg.saveregvars(exprasmlist,all_registers);
  132. { call the mem handling procedures }
  133. case nodetype of
  134. simpledisposen:
  135. begin
  136. if left_needs_initfinal then
  137. begin
  138. new(r);
  139. reset_reference(r^);
  140. r^.symbol:=tstoreddef(tpointerdef(left.resulttype.def).pointertype.def).get_rtti_label(initrtti);
  141. emitpushreferenceaddr(r^);
  142. dispose(r);
  143. { push pointer adress }
  144. emit_push_loc(left.location);
  145. { save left and free its registers }
  146. saveleft;
  147. emitcall('FPC_FINALIZE');
  148. { push left again as parameter for freemem }
  149. emit_push_mem(lefttemp);
  150. tg.ungetiftemp(exprasmlist,lefttemp);
  151. end
  152. else
  153. begin
  154. emit_push_loc(left.location);
  155. rg.del_location(exprasmlist,left.location);
  156. end;
  157. emitcall('FPC_FREEMEM');
  158. end;
  159. simplenewn:
  160. begin
  161. { determines the size of the mem block }
  162. push_int(tpointerdef(left.resulttype.def).pointertype.def.size);
  163. emit_push_lea_loc(left.location,true);
  164. { save left and free its registers }
  165. if left_needs_initfinal then
  166. saveleft;
  167. emitcall('FPC_GETMEM');
  168. if left_needs_initfinal then
  169. begin
  170. new(r);
  171. reset_reference(r^);
  172. r^.symbol:=tstoreddef(tpointerdef(left.resulttype.def).pointertype.def).get_rtti_label(initrtti);
  173. emitpushreferenceaddr(r^);
  174. dispose(r);
  175. emit_push_mem(lefttemp);
  176. tg.ungetiftemp(exprasmlist,lefttemp);
  177. emitcall('FPC_INITIALIZE');
  178. end;
  179. end;
  180. end;
  181. rg.restoreusedregisters(exprasmlist,pushed);
  182. { may be load ESI }
  183. maybe_loadself;
  184. end;
  185. {*****************************************************************************
  186. TI386DEREFNODE
  187. *****************************************************************************}
  188. procedure ti386derefnode.pass_2;
  189. begin
  190. inherited pass_2;
  191. if tpointerdef(left.resulttype.def).is_far then
  192. location.reference.segment:=R_FS;
  193. if not tpointerdef(left.resulttype.def).is_far and
  194. (cs_gdb_heaptrc in aktglobalswitches) and
  195. (cs_checkpointer in aktglobalswitches) then
  196. begin
  197. emit_reg(
  198. A_PUSH,S_L,location.reference.base);
  199. emitcall('FPC_CHECKPOINTER');
  200. end;
  201. end;
  202. {*****************************************************************************
  203. TI386VECNODE
  204. *****************************************************************************}
  205. procedure ti386vecnode.pass_2;
  206. var
  207. is_pushed : boolean;
  208. ind,hr : tregister;
  209. //_p : tnode;
  210. function get_mul_size:longint;
  211. begin
  212. if nf_memindex in flags then
  213. get_mul_size:=1
  214. else
  215. begin
  216. if (left.resulttype.def.deftype=arraydef) then
  217. get_mul_size:=tarraydef(left.resulttype.def).elesize
  218. else
  219. get_mul_size:=resulttype.def.size;
  220. end
  221. end;
  222. procedure calc_emit_mul;
  223. var
  224. l1,l2 : longint;
  225. begin
  226. l1:=get_mul_size;
  227. case l1 of
  228. 1,2,4,8 : location.reference.scalefactor:=l1;
  229. else
  230. begin
  231. if ispowerof2(l1,l2) then
  232. emit_const_reg(A_SHL,S_L,l2,ind)
  233. else
  234. emit_const_reg(A_IMUL,S_L,l1,ind);
  235. end;
  236. end;
  237. end;
  238. var
  239. extraoffset : longint;
  240. { rl stores the resulttype.def of the left node, this is necessary }
  241. { to detect if it is an ansistring }
  242. { because in constant nodes which constant index }
  243. { the left tree is removed }
  244. t : tnode;
  245. hp : preference;
  246. href : treference;
  247. tai : Taicpu;
  248. srsym : tsym;
  249. pushed : tpushedsaved;
  250. hightree : tnode;
  251. hl,otl,ofl : tasmlabel;
  252. begin
  253. secondpass(left);
  254. { we load the array reference to location }
  255. { an ansistring needs to be dereferenced }
  256. if is_ansistring(left.resulttype.def) or
  257. is_widestring(left.resulttype.def) then
  258. begin
  259. reset_reference(location.reference);
  260. if nf_callunique in flags then
  261. begin
  262. if left.location.loc<>LOC_REFERENCE then
  263. begin
  264. CGMessage(cg_e_illegal_expression);
  265. exit;
  266. end;
  267. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  268. emitpushreferenceaddr(left.location.reference);
  269. rg.saveregvars(exprasmlist,all_registers);
  270. if is_ansistring(left.resulttype.def) then
  271. emitcall('FPC_ANSISTR_UNIQUE')
  272. else
  273. emitcall('FPC_WIDESTR_UNIQUE');
  274. maybe_loadself;
  275. rg.restoreusedregisters(exprasmlist,pushed);
  276. end;
  277. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  278. begin
  279. location.reference.base:=left.location.register;
  280. end
  281. else
  282. begin
  283. rg.del_reference(exprasmlist,left.location.reference);
  284. location.reference.base:=rg.getregisterint(exprasmlist);
  285. emit_ref_reg(A_MOV,S_L,
  286. newreference(left.location.reference),
  287. location.reference.base);
  288. end;
  289. { check for a zero length string,
  290. we can use the ansistring routine here }
  291. if (cs_check_range in aktlocalswitches) then
  292. begin
  293. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  294. emit_reg(A_PUSH,S_L,location.reference.base);
  295. rg.saveregvars(exprasmlist,all_registers);
  296. emitcall('FPC_ANSISTR_CHECKZERO');
  297. maybe_loadself;
  298. rg.restoreusedregisters(exprasmlist,pushed);
  299. end;
  300. if is_ansistring(left.resulttype.def) then
  301. { in ansistrings S[1] is pchar(S)[0] !! }
  302. dec(location.reference.offset)
  303. else
  304. begin
  305. { in widestrings S[1] is pwchar(S)[0] !! }
  306. dec(location.reference.offset,2);
  307. // emit_const_reg(A_SHL,S_L,
  308. // 1,location.reference.base);
  309. end;
  310. { we've also to keep left up-to-date, because it is used }
  311. { if a constant array index occurs, subject to change (FK) }
  312. set_location(left.location,location);
  313. end
  314. else if is_dynamic_array(left.resulttype.def) then
  315. { ... also a dynamic string }
  316. begin
  317. reset_reference(location.reference);
  318. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  319. begin
  320. location.reference.base:=left.location.register;
  321. end
  322. else
  323. begin
  324. rg.del_reference(exprasmlist,left.location.reference);
  325. location.reference.base:=rg.getregisterint(exprasmlist);
  326. emit_ref_reg(A_MOV,S_L,
  327. newreference(left.location.reference),
  328. location.reference.base);
  329. end;
  330. {$warning FIXME}
  331. { check for a zero length string,
  332. we can use the ansistring routine here }
  333. if (cs_check_range in aktlocalswitches) then
  334. begin
  335. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  336. emit_reg(A_PUSH,S_L,location.reference.base);
  337. rg.saveregvars(exprasmlist,all_registers);
  338. emitcall('FPC_ANSISTR_CHECKZERO');
  339. maybe_loadself;
  340. rg.restoreusedregisters(exprasmlist,pushed);
  341. end;
  342. { we've also to keep left up-to-date, because it is used }
  343. { if a constant array index occurs, subject to change (FK) }
  344. set_location(left.location,location);
  345. end
  346. else
  347. set_location(location,left.location);
  348. { offset can only differ from 0 if arraydef }
  349. if (left.resulttype.def.deftype=arraydef) and
  350. not(is_dynamic_array(left.resulttype.def)) then
  351. dec(location.reference.offset,
  352. get_mul_size*tarraydef(left.resulttype.def).lowrange);
  353. if right.nodetype=ordconstn then
  354. begin
  355. { offset can only differ from 0 if arraydef }
  356. if (left.resulttype.def.deftype=arraydef) then
  357. begin
  358. if not(is_open_array(left.resulttype.def)) and
  359. not(is_array_of_const(left.resulttype.def)) and
  360. not(is_dynamic_array(left.resulttype.def)) then
  361. begin
  362. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  363. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  364. begin
  365. if (cs_check_range in aktlocalswitches) then
  366. CGMessage(parser_e_range_check_error)
  367. else
  368. CGMessage(parser_w_range_check_error);
  369. end;
  370. dec(left.location.reference.offset,
  371. get_mul_size*tarraydef(left.resulttype.def).lowrange);
  372. end
  373. else
  374. begin
  375. { range checking for open and dynamic arrays !!!! }
  376. {$warning FIXME}
  377. {!!!!!!!!!!!!!!!!!}
  378. end;
  379. end
  380. else if (left.resulttype.def.deftype=stringdef) then
  381. begin
  382. if (tordconstnode(right).value=0) and not(is_shortstring(left.resulttype.def)) then
  383. CGMessage(cg_e_can_access_element_zero);
  384. if (cs_check_range in aktlocalswitches) then
  385. case tstringdef(left.resulttype.def).string_typ of
  386. { it's the same for ansi- and wide strings }
  387. st_widestring,
  388. st_ansistring:
  389. begin
  390. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  391. push_int(tordconstnode(right).value);
  392. hp:=newreference(location.reference);
  393. dec(hp^.offset,7);
  394. emit_ref(A_PUSH,S_L,hp);
  395. rg.saveregvars(exprasmlist,all_registers);
  396. emitcall('FPC_ANSISTR_RANGECHECK');
  397. rg.restoreusedregisters(exprasmlist,pushed);
  398. maybe_loadself;
  399. end;
  400. st_shortstring:
  401. begin
  402. {!!!!!!!!!!!!!!!!!}
  403. end;
  404. st_longstring:
  405. begin
  406. {!!!!!!!!!!!!!!!!!}
  407. end;
  408. end;
  409. end;
  410. inc(left.location.reference.offset,
  411. get_mul_size*tordconstnode(right).value);
  412. if nf_memseg in flags then
  413. left.location.reference.segment:=R_FS;
  414. {
  415. left.resulttype:=resulttype.def;
  416. disposetree(right);
  417. _p:=left;
  418. putnode(p);
  419. p:=_p;
  420. }
  421. set_location(location,left.location);
  422. end
  423. else
  424. { not nodetype=ordconstn }
  425. begin
  426. if (cs_regalloc in aktglobalswitches) and
  427. { if we do range checking, we don't }
  428. { need that fancy code (it would be }
  429. { buggy) }
  430. not(cs_check_range in aktlocalswitches) and
  431. (left.resulttype.def.deftype=arraydef) then
  432. begin
  433. extraoffset:=0;
  434. if (right.nodetype=addn) then
  435. begin
  436. if taddnode(right).right.nodetype=ordconstn then
  437. begin
  438. extraoffset:=tordconstnode(taddnode(right).right).value;
  439. t:=taddnode(right).left;
  440. { First pass processed this with the assumption }
  441. { that there was an add node which may require an }
  442. { extra register. Fake it or die with IE10 (JM) }
  443. t.registers32 := taddnode(right).registers32;
  444. taddnode(right).left:=nil;
  445. right.free;
  446. right:=t;
  447. end
  448. else if tordconstnode(taddnode(right).left).nodetype=ordconstn then
  449. begin
  450. extraoffset:=tordconstnode(taddnode(right).left).value;
  451. t:=taddnode(right).right;
  452. t.registers32 := right.registers32;
  453. taddnode(right).right:=nil;
  454. right.free;
  455. right:=t;
  456. end;
  457. end
  458. else if (right.nodetype=subn) then
  459. begin
  460. if taddnode(right).right.nodetype=ordconstn then
  461. begin
  462. { this was "extraoffset:=right.right.value;" Looks a bit like
  463. copy-paste bug :) (JM) }
  464. extraoffset:=-tordconstnode(taddnode(right).right).value;
  465. t:=taddnode(right).left;
  466. t.registers32 := right.registers32;
  467. taddnode(right).left:=nil;
  468. right.free;
  469. right:=t;
  470. end
  471. { You also have to negate right.right in this case! I can't add an
  472. unaryminusn without causing a crash, so I've disabled it (JM)
  473. else if right.left.nodetype=ordconstn then
  474. begin
  475. extraoffset:=right.left.value;
  476. t:=right.right;
  477. t^.registers32 := right.registers32;
  478. putnode(right);
  479. putnode(right.left);
  480. right:=t;
  481. end;}
  482. end;
  483. inc(location.reference.offset,
  484. get_mul_size*extraoffset);
  485. end;
  486. { calculate from left to right }
  487. if (location.loc<>LOC_REFERENCE) and
  488. (location.loc<>LOC_MEM) then
  489. CGMessage(cg_e_illegal_expression);
  490. if (right.location.loc=LOC_JUMP) then
  491. begin
  492. otl:=truelabel;
  493. getlabel(truelabel);
  494. ofl:=falselabel;
  495. getlabel(falselabel);
  496. end;
  497. is_pushed:=maybe_push(right.registers32,self,false);
  498. secondpass(right);
  499. if is_pushed then
  500. restore(self,false);
  501. { here we change the location of right
  502. and the update was forgotten so it
  503. led to wrong code in emitrangecheck later PM
  504. so make range check before }
  505. if cs_check_range in aktlocalswitches then
  506. begin
  507. if left.resulttype.def.deftype=arraydef then
  508. begin
  509. if is_open_array(left.resulttype.def) or
  510. is_array_of_const(left.resulttype.def) then
  511. begin
  512. reset_reference(href);
  513. tarraydef(left.resulttype.def).genrangecheck;
  514. href.symbol:=newasmsymbol(tarraydef(left.resulttype.def).getrangecheckstring);
  515. href.offset:=4;
  516. srsym:=searchsymonlyin(tloadnode(left).symtable,
  517. 'high'+tvarsym(tloadnode(left).symtableentry).name);
  518. hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
  519. firstpass(hightree);
  520. secondpass(hightree);
  521. emit_mov_loc_ref(hightree.location,href,S_L,true);
  522. hightree.free;
  523. hightree:=nil;
  524. end;
  525. cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
  526. end;
  527. end;
  528. case right.location.loc of
  529. LOC_REGISTER:
  530. begin
  531. ind:=right.location.register;
  532. case right.resulttype.def.size of
  533. 1:
  534. begin
  535. hr:=reg8toreg32(ind);
  536. emit_reg_reg(A_MOVZX,S_BL,ind,hr);
  537. ind:=hr;
  538. end;
  539. 2:
  540. begin
  541. hr:=reg16toreg32(ind);
  542. emit_reg_reg(A_MOVZX,S_WL,ind,hr);
  543. ind:=hr;
  544. end;
  545. end;
  546. end;
  547. LOC_CREGISTER:
  548. begin
  549. ind:=rg.getregisterint(exprasmlist);
  550. case right.resulttype.def.size of
  551. 1:
  552. emit_reg_reg(A_MOVZX,S_BL,right.location.register,ind);
  553. 2:
  554. emit_reg_reg(A_MOVZX,S_WL,right.location.register,ind);
  555. 4:
  556. emit_reg_reg(A_MOV,S_L,right.location.register,ind);
  557. end;
  558. end;
  559. LOC_FLAGS:
  560. begin
  561. ind:=rg.getregisterint(exprasmlist);
  562. emit_flag2reg(right.location.resflags,reg32toreg8(ind));
  563. emit_reg_reg(A_MOVZX,S_BL,reg32toreg8(ind),ind);
  564. end;
  565. LOC_JUMP :
  566. begin
  567. ind:=rg.getregisterint(exprasmlist);
  568. emitlab(truelabel);
  569. truelabel:=otl;
  570. emit_const_reg(A_MOV,S_L,1,ind);
  571. getlabel(hl);
  572. emitjmp(C_None,hl);
  573. emitlab(falselabel);
  574. falselabel:=ofl;
  575. emit_reg_reg(A_XOR,S_L,ind,ind);
  576. emitlab(hl);
  577. end;
  578. LOC_REFERENCE,LOC_MEM :
  579. begin
  580. rg.del_reference(exprasmlist,right.location.reference);
  581. ind:=rg.getregisterint(exprasmlist);
  582. { Booleans are stored in an 8 bit memory location, so
  583. the use of MOVL is not correct }
  584. case right.resulttype.def.size of
  585. 1 : tai:=Taicpu.Op_ref_reg(A_MOVZX,S_BL,newreference(right.location.reference),ind);
  586. 2 : tai:=Taicpu.Op_ref_reg(A_MOVZX,S_WL,newreference(right.location.reference),ind);
  587. 4 : tai:=Taicpu.Op_ref_reg(A_MOV,S_L,newreference(right.location.reference),ind);
  588. end;
  589. exprasmList.concat(tai);
  590. end;
  591. else
  592. internalerror(5913428);
  593. end;
  594. { produce possible range check code: }
  595. if cs_check_range in aktlocalswitches then
  596. begin
  597. if left.resulttype.def.deftype=arraydef then
  598. begin
  599. { done defore (PM) }
  600. end
  601. else if (left.resulttype.def.deftype=stringdef) then
  602. begin
  603. case tstringdef(left.resulttype.def).string_typ of
  604. { it's the same for ansi- and wide strings }
  605. st_widestring,
  606. st_ansistring:
  607. begin
  608. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  609. emit_reg(A_PUSH,S_L,ind);
  610. hp:=newreference(location.reference);
  611. dec(hp^.offset,7);
  612. emit_ref(A_PUSH,S_L,hp);
  613. rg.saveregvars(exprasmlist,all_registers);
  614. emitcall('FPC_ANSISTR_RANGECHECK');
  615. rg.restoreusedregisters(exprasmlist,pushed);
  616. maybe_loadself;
  617. end;
  618. st_shortstring:
  619. begin
  620. {!!!!!!!!!!!!!!!!!}
  621. end;
  622. st_longstring:
  623. begin
  624. {!!!!!!!!!!!!!!!!!}
  625. end;
  626. end;
  627. end;
  628. end;
  629. if location.reference.index=R_NO then
  630. begin
  631. location.reference.index:=ind;
  632. calc_emit_mul;
  633. end
  634. else
  635. begin
  636. if location.reference.base=R_NO then
  637. begin
  638. case location.reference.scalefactor of
  639. 2 : emit_const_reg(A_SHL,S_L,1,location.reference.index);
  640. 4 : emit_const_reg(A_SHL,S_L,2,location.reference.index);
  641. 8 : emit_const_reg(A_SHL,S_L,3,location.reference.index);
  642. end;
  643. calc_emit_mul;
  644. location.reference.base:=location.reference.index;
  645. location.reference.index:=ind;
  646. end
  647. else
  648. begin
  649. emit_ref_reg(
  650. A_LEA,S_L,newreference(location.reference),
  651. location.reference.index);
  652. rg.ungetregisterint(exprasmlist,location.reference.base);
  653. { the symbol offset is loaded, }
  654. { so release the symbol name and set symbol }
  655. { to nil }
  656. location.reference.symbol:=nil;
  657. location.reference.offset:=0;
  658. calc_emit_mul;
  659. location.reference.base:=location.reference.index;
  660. location.reference.index:=ind;
  661. end;
  662. end;
  663. if nf_memseg in flags then
  664. location.reference.segment:=R_FS;
  665. end;
  666. end;
  667. begin
  668. cnewnode:=ti386newnode;
  669. csimplenewdisposenode:=ti386simplenewdisposenode;
  670. caddrnode:=ti386addrnode;
  671. cderefnode:=ti386derefnode;
  672. cvecnode:=ti386vecnode;
  673. end.
  674. {
  675. $Log$
  676. Revision 1.22 2002-04-01 09:44:04 jonas
  677. * better fix for new/dispose bug with init/final data
  678. Revision 1.21 2002/03/31 20:26:39 jonas
  679. + a_loadfpu_* and a_loadmm_* methods in tcg
  680. * register allocation is now handled by a class and is mostly processor
  681. independent (+rgobj.pas and i386/rgcpu.pas)
  682. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  683. * some small improvements and fixes to the optimizer
  684. * some register allocation fixes
  685. * some fpuvaroffset fixes in the unary minus node
  686. * push/popusedregisters is now called rg.save/restoreusedregisters and
  687. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  688. also better optimizable)
  689. * fixed and optimized register saving/restoring for new/dispose nodes
  690. * LOC_FPU locations now also require their "register" field to be set to
  691. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  692. - list field removed of the tnode class because it's not used currently
  693. and can cause hard-to-find bugs
  694. Revision 1.20 2002/03/04 19:10:14 peter
  695. * removed compiler warnings
  696. Revision 1.19 2001/12/30 17:24:47 jonas
  697. * range checking is now processor independent (part in cgobj,
  698. part in cg64f32) and should work correctly again (it needed
  699. some changes after the changes of the low and high of
  700. tordef's to int64)
  701. * maketojumpbool() is now processor independent (in ncgutil)
  702. * getregister32 is now called getregisterint
  703. Revision 1.18 2001/12/03 21:48:43 peter
  704. * freemem change to value parameter
  705. * torddef low/high range changed to int64
  706. Revision 1.17 2001/09/30 16:17:17 jonas
  707. * made most constant and mem handling processor independent
  708. Revision 1.16 2001/08/30 20:13:57 peter
  709. * rtti/init table updates
  710. * rttisym for reusable global rtti/init info
  711. * support published for interfaces
  712. Revision 1.15 2001/08/26 13:37:00 florian
  713. * some cg reorganisation
  714. * some PPC updates
  715. Revision 1.14 2001/07/08 21:00:18 peter
  716. * various widestring updates, it works now mostly without charset
  717. mapping supported
  718. Revision 1.13 2001/04/18 22:02:03 peter
  719. * registration of targets and assemblers
  720. Revision 1.12 2001/04/13 01:22:19 peter
  721. * symtable change to classes
  722. * range check generation and errors fixed, make cycle DEBUG=1 works
  723. * memory leaks fixed
  724. Revision 1.11 2001/04/02 21:20:38 peter
  725. * resulttype rewrite
  726. Revision 1.10 2001/03/11 22:58:52 peter
  727. * getsym redesign, removed the globals srsym,srsymtable
  728. Revision 1.9 2001/02/02 22:38:00 peter
  729. * fixed crash with new(precord), merged
  730. Revision 1.8 2000/12/25 00:07:33 peter
  731. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  732. tlinkedlist objects)
  733. Revision 1.7 2000/12/05 11:44:33 jonas
  734. + new integer regvar handling, should be much more efficient
  735. Revision 1.6 2000/11/29 00:30:48 florian
  736. * unused units removed from uses clause
  737. * some changes for widestrings
  738. Revision 1.5 2000/11/04 14:25:24 florian
  739. + merged Attila's changes for interfaces, not tested yet
  740. Revision 1.4 2000/10/31 22:02:57 peter
  741. * symtable splitted, no real code changes
  742. Revision 1.3 2000/10/31 14:18:53 jonas
  743. * merged double deleting of left location when using a temp in
  744. secondwith (merged from fixes branch). This also fixes web bug1194
  745. Revision 1.2 2000/10/21 18:16:13 florian
  746. * a lot of changes:
  747. - basic dyn. array support
  748. - basic C++ support
  749. - some work for interfaces done
  750. ....
  751. Revision 1.1 2000/10/15 09:33:32 peter
  752. * moved n386*.pas to i386/ cpu_target dir
  753. Revision 1.2 2000/10/14 21:52:54 peter
  754. * fixed memory leaks
  755. Revision 1.1 2000/10/14 10:14:49 peter
  756. * moehrendorf oct 2000 rewrite
  757. }