n386mem.pas 30 KB

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