cg386flw.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Generate i386 assembler for nodes that influence the flow
  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 cg386flw;
  19. interface
  20. uses
  21. tree;
  22. procedure second_while_repeatn(var p : ptree);
  23. procedure secondifn(var p : ptree);
  24. procedure secondfor(var p : ptree);
  25. procedure secondexitn(var p : ptree);
  26. procedure secondbreakn(var p : ptree);
  27. procedure secondcontinuen(var p : ptree);
  28. procedure secondgoto(var p : ptree);
  29. procedure secondlabel(var p : ptree);
  30. procedure secondraise(var p : ptree);
  31. procedure secondtryexcept(var p : ptree);
  32. procedure secondtryfinally(var p : ptree);
  33. procedure secondfail(var p : ptree);
  34. implementation
  35. uses
  36. cobjects,verbose,globals,systems,
  37. symtable,aasm,i386,types,
  38. cgi386,cgai386,temp_gen,tgeni386,hcodegen;
  39. {*****************************************************************************
  40. Second_While_RepeatN
  41. *****************************************************************************}
  42. procedure second_while_repeatn(var p : ptree);
  43. var
  44. l1,l2,l3,oldclabel,oldblabel : plabel;
  45. otlabel,oflabel : plabel;
  46. begin
  47. getlabel(l1);
  48. getlabel(l2);
  49. { arrange continue and breaklabels: }
  50. oldclabel:=aktcontinuelabel;
  51. oldblabel:=aktbreaklabel;
  52. if p^.treetype=repeatn then
  53. begin
  54. emitl(A_LABEL,l1);
  55. aktcontinuelabel:=l1;
  56. aktbreaklabel:=l2;
  57. cleartempgen;
  58. if assigned(p^.right) then
  59. secondpass(p^.right);
  60. otlabel:=truelabel;
  61. oflabel:=falselabel;
  62. truelabel:=l2;
  63. falselabel:=l1;
  64. cleartempgen;
  65. secondpass(p^.left);
  66. maketojumpbool(p^.left);
  67. emitl(A_LABEL,l2);
  68. truelabel:=otlabel;
  69. falselabel:=oflabel;
  70. end
  71. else
  72. begin
  73. { handling code at the end as it is much more efficient }
  74. emitl(A_JMP,l2);
  75. emitl(A_LABEL,l1);
  76. cleartempgen;
  77. getlabel(l3);
  78. aktcontinuelabel:=l2;
  79. aktbreaklabel:=l3;
  80. if assigned(p^.right) then
  81. secondpass(p^.right);
  82. emitl(A_LABEL,l2);
  83. otlabel:=truelabel;
  84. oflabel:=falselabel;
  85. truelabel:=l1;
  86. falselabel:=l3;
  87. cleartempgen;
  88. secondpass(p^.left);
  89. maketojumpbool(p^.left);
  90. emitl(A_LABEL,l3);
  91. truelabel:=otlabel;
  92. falselabel:=oflabel;
  93. end;
  94. aktcontinuelabel:=oldclabel;
  95. aktbreaklabel:=oldblabel;
  96. end;
  97. {*****************************************************************************
  98. SecondIfN
  99. *****************************************************************************}
  100. procedure secondifn(var p : ptree);
  101. var
  102. hl,otlabel,oflabel : plabel;
  103. begin
  104. otlabel:=truelabel;
  105. oflabel:=falselabel;
  106. getlabel(truelabel);
  107. getlabel(falselabel);
  108. cleartempgen;
  109. secondpass(p^.left);
  110. maketojumpbool(p^.left);
  111. if assigned(p^.right) then
  112. begin
  113. emitl(A_LABEL,truelabel);
  114. cleartempgen;
  115. secondpass(p^.right);
  116. end;
  117. if assigned(p^.t1) then
  118. begin
  119. if assigned(p^.right) then
  120. begin
  121. getlabel(hl);
  122. emitl(A_JMP,hl);
  123. end;
  124. emitl(A_LABEL,falselabel);
  125. cleartempgen;
  126. secondpass(p^.t1);
  127. if assigned(p^.right) then
  128. emitl(A_LABEL,hl);
  129. end
  130. else
  131. emitl(A_LABEL,falselabel);
  132. if not(assigned(p^.right)) then
  133. emitl(A_LABEL,truelabel);
  134. truelabel:=otlabel;
  135. falselabel:=oflabel;
  136. end;
  137. {*****************************************************************************
  138. SecondFor
  139. *****************************************************************************}
  140. procedure secondfor(var p : ptree);
  141. var
  142. l3,oldclabel,oldblabel : plabel;
  143. omitfirstcomp,temptovalue : boolean;
  144. hs : byte;
  145. temp1 : treference;
  146. hop : tasmop;
  147. cmpreg,cmp32 : tregister;
  148. opsize : topsize;
  149. count_var_is_signed : boolean;
  150. begin
  151. oldclabel:=aktcontinuelabel;
  152. oldblabel:=aktbreaklabel;
  153. getlabel(aktcontinuelabel);
  154. getlabel(aktbreaklabel);
  155. getlabel(l3);
  156. { could we spare the first comparison ? }
  157. omitfirstcomp:=false;
  158. if p^.right^.treetype=ordconstn then
  159. if p^.left^.right^.treetype=ordconstn then
  160. omitfirstcomp:=(p^.backward and (p^.left^.right^.value>=p^.right^.value))
  161. or (not(p^.backward) and (p^.left^.right^.value<=p^.right^.value));
  162. { only calculate reference }
  163. cleartempgen;
  164. secondpass(p^.t2);
  165. if not(simple_loadn) then
  166. Message(cg_e_illegal_count_var);
  167. { produce start assignment }
  168. cleartempgen;
  169. secondpass(p^.left);
  170. count_var_is_signed:=is_signed(porddef(p^.t2^.resulttype));
  171. hs:=p^.t2^.resulttype^.size;
  172. cmp32:=getregister32;
  173. case hs of
  174. 1 : begin
  175. opsize:=S_B;
  176. cmpreg:=reg32toreg8(cmp32);
  177. end;
  178. 2 : begin
  179. opsize:=S_W;
  180. cmpreg:=reg32toreg16(cmp32);
  181. end;
  182. 4 : begin
  183. opsize:=S_L;
  184. cmpreg:=cmp32;
  185. end;
  186. end;
  187. cleartempgen;
  188. secondpass(p^.right);
  189. { calculate pointer value and check if changeable and if so }
  190. { load into temporary variable }
  191. if p^.right^.treetype<>ordconstn then
  192. begin
  193. temp1.symbol:=nil;
  194. gettempofsizereference(hs,temp1);
  195. temptovalue:=true;
  196. if (p^.right^.location.loc=LOC_REGISTER) or
  197. (p^.right^.location.loc=LOC_CREGISTER) then
  198. begin
  199. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,p^.right^.location.register,
  200. newreference(temp1))));
  201. end
  202. else
  203. concatcopy(p^.right^.location.reference,temp1,hs,false);
  204. end
  205. else temptovalue:=false;
  206. if temptovalue then
  207. begin
  208. if p^.t2^.location.loc=LOC_CREGISTER then
  209. begin
  210. exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,opsize,newreference(temp1),
  211. p^.t2^.location.register)));
  212. end
  213. else
  214. begin
  215. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,newreference(p^.t2^.location.reference),
  216. cmpreg)));
  217. exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,opsize,newreference(temp1),
  218. cmpreg)));
  219. end;
  220. end
  221. else
  222. begin
  223. if not(omitfirstcomp) then
  224. begin
  225. if p^.t2^.location.loc=LOC_CREGISTER then
  226. exprasmlist^.concat(new(pai386,op_const_reg(A_CMP,opsize,p^.right^.value,
  227. p^.t2^.location.register)))
  228. else
  229. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,opsize,p^.right^.value,
  230. newreference(p^.t2^.location.reference))));
  231. end;
  232. end;
  233. if p^.backward then
  234. if count_var_is_signed then
  235. hop:=A_JL
  236. else hop:=A_JB
  237. else
  238. if count_var_is_signed then
  239. hop:=A_JG
  240. else hop:=A_JA;
  241. if not(omitfirstcomp) or temptovalue then
  242. emitl(hop,aktbreaklabel);
  243. emitl(A_LABEL,l3);
  244. { help register must not be in instruction block }
  245. cleartempgen;
  246. if assigned(p^.t1) then
  247. secondpass(p^.t1);
  248. emitl(A_LABEL,aktcontinuelabel);
  249. { makes no problems there }
  250. cleartempgen;
  251. { demand help register again }
  252. cmp32:=getregister32;
  253. case hs of
  254. 1 : begin
  255. opsize:=S_B;
  256. cmpreg:=reg32toreg8(cmp32);
  257. end;
  258. 2 : begin
  259. opsize:=S_W;
  260. cmpreg:=reg32toreg16(cmp32);
  261. end;
  262. 4 : opsize:=S_L;
  263. end;
  264. { produce comparison and the corresponding }
  265. { jump }
  266. if temptovalue then
  267. begin
  268. if p^.t2^.location.loc=LOC_CREGISTER then
  269. begin
  270. exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,opsize,newreference(temp1),
  271. p^.t2^.location.register)));
  272. end
  273. else
  274. begin
  275. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,newreference(p^.t2^.location.reference),
  276. cmpreg)));
  277. exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,opsize,newreference(temp1),
  278. cmpreg)));
  279. end;
  280. end
  281. else
  282. begin
  283. if p^.t2^.location.loc=LOC_CREGISTER then
  284. exprasmlist^.concat(new(pai386,op_const_reg(A_CMP,opsize,p^.right^.value,
  285. p^.t2^.location.register)))
  286. else
  287. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,opsize,p^.right^.value,
  288. newreference(p^.t2^.location.reference))));
  289. end;
  290. if p^.backward then
  291. if count_var_is_signed then
  292. hop:=A_JLE
  293. else
  294. hop :=A_JBE
  295. else
  296. if count_var_is_signed then
  297. hop:=A_JGE
  298. else
  299. hop:=A_JAE;
  300. emitl(hop,aktbreaklabel);
  301. { according to count direction DEC or INC... }
  302. { must be after the test because of 0to 255 for bytes !! }
  303. if p^.backward then
  304. hop:=A_DEC
  305. else hop:=A_INC;
  306. if p^.t2^.location.loc=LOC_CREGISTER then
  307. exprasmlist^.concat(new(pai386,op_reg(hop,opsize,p^.t2^.location.register)))
  308. else
  309. exprasmlist^.concat(new(pai386,op_ref(hop,opsize,newreference(p^.t2^.location.reference))));
  310. emitl(A_JMP,l3);
  311. { this is the break label: }
  312. emitl(A_LABEL,aktbreaklabel);
  313. ungetregister32(cmp32);
  314. if temptovalue then
  315. ungetiftemp(temp1);
  316. aktcontinuelabel:=oldclabel;
  317. aktbreaklabel:=oldblabel;
  318. end;
  319. {*****************************************************************************
  320. SecondExitN
  321. *****************************************************************************}
  322. procedure secondexitn(var p : ptree);
  323. var
  324. is_mem : boolean;
  325. {op : tasmop;
  326. s : topsize;}
  327. otlabel,oflabel : plabel;
  328. label
  329. do_jmp;
  330. begin
  331. if assigned(p^.left) then
  332. begin
  333. otlabel:=truelabel;
  334. oflabel:=falselabel;
  335. getlabel(truelabel);
  336. getlabel(falselabel);
  337. secondpass(p^.left);
  338. case p^.left^.location.loc of
  339. LOC_FPU : goto do_jmp;
  340. LOC_MEM,LOC_REFERENCE : is_mem:=true;
  341. LOC_CREGISTER,
  342. LOC_REGISTER : is_mem:=false;
  343. LOC_FLAGS : begin
  344. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[p^.right^.location.resflags],S_B,R_AL)));
  345. goto do_jmp;
  346. end;
  347. LOC_JUMP : begin
  348. emitl(A_LABEL,truelabel);
  349. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,1,R_AL)));
  350. emitl(A_JMP,aktexit2label);
  351. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_B,R_AL,R_AL)));
  352. goto do_jmp;
  353. end;
  354. else internalerror(2001);
  355. end;
  356. if (procinfo.retdef^.deftype=orddef) then
  357. begin
  358. case porddef(procinfo.retdef)^.typ of
  359. s32bit,u32bit,bool32bit : if is_mem then
  360. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  361. newreference(p^.left^.location.reference),R_EAX)))
  362. else
  363. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,R_EAX);
  364. u8bit,s8bit,uchar,bool8bit : if is_mem then
  365. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_B,
  366. newreference(p^.left^.location.reference),R_AL)))
  367. else
  368. emit_reg_reg(A_MOV,S_B,p^.left^.location.register,R_AL);
  369. s16bit,u16bit,bool16bit : if is_mem then
  370. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_W,
  371. newreference(p^.left^.location.reference),R_AX)))
  372. else
  373. emit_reg_reg(A_MOV,S_W,p^.left^.location.register,R_AX);
  374. end;
  375. end
  376. else
  377. if (procinfo.retdef^.deftype in [pointerdef,enumdef,procvardef]) then
  378. begin
  379. if is_mem then
  380. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  381. newreference(p^.left^.location.reference),R_EAX)))
  382. else
  383. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  384. p^.left^.location.register,R_EAX)));
  385. end
  386. else
  387. if (procinfo.retdef^.deftype=floatdef) then
  388. begin
  389. if pfloatdef(procinfo.retdef)^.typ=f32bit then
  390. begin
  391. if is_mem then
  392. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  393. newreference(p^.left^.location.reference),R_EAX)))
  394. else
  395. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,R_EAX);
  396. end
  397. else
  398. if is_mem then
  399. floatload(pfloatdef(procinfo.retdef)^.typ,p^.left^.location.reference);
  400. end;
  401. do_jmp:
  402. truelabel:=otlabel;
  403. falselabel:=oflabel;
  404. emitl(A_JMP,aktexit2label);
  405. end
  406. else
  407. begin
  408. emitl(A_JMP,aktexitlabel);
  409. end;
  410. end;
  411. {*****************************************************************************
  412. SecondBreakN
  413. *****************************************************************************}
  414. procedure secondbreakn(var p : ptree);
  415. begin
  416. if aktbreaklabel<>nil then
  417. emitl(A_JMP,aktbreaklabel)
  418. else
  419. Message(cg_e_break_not_allowed);
  420. end;
  421. {*****************************************************************************
  422. SecondContinueN
  423. *****************************************************************************}
  424. procedure secondcontinuen(var p : ptree);
  425. begin
  426. if aktcontinuelabel<>nil then
  427. emitl(A_JMP,aktcontinuelabel)
  428. else
  429. Message(cg_e_continue_not_allowed);
  430. end;
  431. {*****************************************************************************
  432. SecondGoto
  433. *****************************************************************************}
  434. procedure secondgoto(var p : ptree);
  435. begin
  436. emitl(A_JMP,p^.labelnr);
  437. end;
  438. {*****************************************************************************
  439. SecondLabel
  440. *****************************************************************************}
  441. procedure secondlabel(var p : ptree);
  442. begin
  443. emitl(A_LABEL,p^.labelnr);
  444. cleartempgen;
  445. secondpass(p^.left);
  446. end;
  447. {*****************************************************************************
  448. SecondRaise
  449. *****************************************************************************}
  450. procedure secondraise(var p : ptree);
  451. var
  452. a : plabel;
  453. begin
  454. if assigned(p^.left) then
  455. begin
  456. { generate the address }
  457. if assigned(p^.right) then
  458. begin
  459. secondpass(p^.right);
  460. if codegenerror then
  461. exit;
  462. end
  463. else
  464. begin
  465. getlabel(a);
  466. emitl(A_LABEL,a);
  467. exprasmlist^.concat(new(pai386,
  468. op_csymbol(A_PUSH,S_L,newcsymbol(lab2str(a),0))));
  469. end;
  470. secondpass(p^.left);
  471. if codegenerror then
  472. exit;
  473. case p^.left^.location.loc of
  474. LOC_MEM,LOC_REFERENCE:
  475. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  476. LOC_CREGISTER,LOC_REGISTER : exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,
  477. p^.left^.location.register)));
  478. else Message(sym_e_type_mismatch);
  479. end;
  480. emitcall('DO_RAISE',true);
  481. end
  482. else
  483. emitcall('DO_RERAISE',true);
  484. end;
  485. {*****************************************************************************
  486. SecondTryExcept
  487. *****************************************************************************}
  488. procedure secondtryexcept(var p : ptree);
  489. begin
  490. end;
  491. {*****************************************************************************
  492. SecondTryFinally
  493. *****************************************************************************}
  494. procedure secondtryfinally(var p : ptree);
  495. begin
  496. end;
  497. {*****************************************************************************
  498. SecondFail
  499. *****************************************************************************}
  500. procedure secondfail(var p : ptree);
  501. var
  502. hp : preference;
  503. begin
  504. {if procinfo.exceptions then
  505. aktproccode.concat(gennasmrec(CALL,S_NO,'HELP_DESTRUCTOR_E'))
  506. else }
  507. { we should know if the constructor is called with a new or not,
  508. how can we do that ???
  509. exprasmlist^.concat(new(pai386,op_csymbol(A_CALL,S_NO,newcsymbol('HELP_DESTRUCTOR',0))));
  510. }
  511. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_L,R_ESI,R_ESI)));
  512. { also reset to zero in the stack }
  513. new(hp);
  514. reset_reference(hp^);
  515. hp^.offset:=procinfo.ESI_offset;
  516. hp^.base:=procinfo.framepointer;
  517. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_ESI,hp)));
  518. exprasmlist^.concat(new(pai_labeled,init(A_JMP,quickexitlabel)));
  519. end;
  520. end.
  521. {
  522. $Log$
  523. Revision 1.3 1998-06-25 08:48:08 florian
  524. * first version of rtti support
  525. Revision 1.2 1998/06/08 13:13:33 pierre
  526. + temporary variables now in temp_gen.pas unit
  527. because it is processor independent
  528. * mppc68k.bat modified to undefine i386 and support_mmx
  529. (which are defaults for i386)
  530. Revision 1.1 1998/06/05 17:44:12 peter
  531. * splitted cgi386
  532. }