tcmat.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Type checking and register allocation for math 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 tcmat;
  19. interface
  20. uses
  21. tree;
  22. procedure firstmoddiv(var p : ptree);
  23. procedure firstshlshr(var p : ptree);
  24. procedure firstumminus(var p : ptree);
  25. procedure firstnot(var p : ptree);
  26. implementation
  27. uses
  28. globtype,systems,tokens,
  29. cobjects,verbose,globals,
  30. symtable,aasm,types,
  31. hcodegen,htypechk,pass_1
  32. {$ifdef i386}
  33. {$ifndef OLDASM}
  34. ,i386base
  35. {$else}
  36. ,i386
  37. {$endif}
  38. {$endif}
  39. {$ifdef m68k}
  40. ,m68k
  41. {$endif}
  42. ;
  43. {*****************************************************************************
  44. FirstModDiv
  45. *****************************************************************************}
  46. procedure firstmoddiv(var p : ptree);
  47. var
  48. t : ptree;
  49. rv,lv : longint;
  50. begin
  51. firstpass(p^.left);
  52. firstpass(p^.right);
  53. if codegenerror then
  54. exit;
  55. { check for division by zero }
  56. rv:=p^.right^.value;
  57. lv:=p^.left^.value;
  58. if is_constintnode(p^.right) and (rv=0) then
  59. begin
  60. Message(parser_e_division_by_zero);
  61. { recover }
  62. rv:=1;
  63. end;
  64. if is_constintnode(p^.left) and is_constintnode(p^.right) then
  65. begin
  66. case p^.treetype of
  67. modn : t:=genordinalconstnode(lv mod rv,s32bitdef);
  68. divn : t:=genordinalconstnode(lv div rv,s32bitdef);
  69. end;
  70. disposetree(p);
  71. firstpass(t);
  72. p:=t;
  73. exit;
  74. end;
  75. if not(p^.right^.resulttype^.deftype=orddef) or
  76. not(porddef(p^.right^.resulttype)^.typ in [s32bit,u32bit]) then
  77. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  78. if not(p^.left^.resulttype^.deftype=orddef) or
  79. not(porddef(p^.left^.resulttype)^.typ in [s32bit,u32bit]) then
  80. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  81. firstpass(p^.left);
  82. firstpass(p^.right);
  83. { the resulttype depends on the right side, because the left becomes }
  84. { always 64 bit }
  85. p^.resulttype:=p^.right^.resulttype;
  86. if codegenerror then
  87. exit;
  88. left_right_max(p);
  89. if p^.left^.registers32<=p^.right^.registers32 then
  90. inc(p^.registers32);
  91. p^.location.loc:=LOC_REGISTER;
  92. end;
  93. {*****************************************************************************
  94. FirstShlShr
  95. *****************************************************************************}
  96. procedure firstshlshr(var p : ptree);
  97. var
  98. t : ptree;
  99. regs : longint;
  100. begin
  101. firstpass(p^.left);
  102. firstpass(p^.right);
  103. if codegenerror then
  104. exit;
  105. if is_constintnode(p^.left) and is_constintnode(p^.right) then
  106. begin
  107. case p^.treetype of
  108. shrn : t:=genordinalconstnode(p^.left^.value shr p^.right^.value,s32bitdef);
  109. shln : t:=genordinalconstnode(p^.left^.value shl p^.right^.value,s32bitdef);
  110. end;
  111. disposetree(p);
  112. firstpass(t);
  113. p:=t;
  114. exit;
  115. end;
  116. { 64 bit ints have their own shift handling }
  117. if not(is_64bitint(p^.left^.resulttype)) then
  118. begin
  119. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  120. firstpass(p^.left);
  121. regs:=1;
  122. p^.resulttype:=s32bitdef;
  123. end
  124. else
  125. begin
  126. p^.resulttype:=p^.left^.resulttype;
  127. regs:=2;
  128. end;
  129. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  130. firstpass(p^.right);
  131. if codegenerror then
  132. exit;
  133. if (p^.right^.treetype<>ordconstn) then
  134. inc(regs);
  135. calcregisters(p,regs,0,0);
  136. p^.location.loc:=LOC_REGISTER;
  137. end;
  138. {*****************************************************************************
  139. FirstUmMinus
  140. *****************************************************************************}
  141. procedure firstumminus(var p : ptree);
  142. var
  143. t : ptree;
  144. minusdef : pprocdef;
  145. begin
  146. firstpass(p^.left);
  147. p^.registers32:=p^.left^.registers32;
  148. p^.registersfpu:=p^.left^.registersfpu;
  149. {$ifdef SUPPORT_MMX}
  150. p^.registersmmx:=p^.left^.registersmmx;
  151. {$endif SUPPORT_MMX}
  152. p^.resulttype:=p^.left^.resulttype;
  153. if codegenerror then
  154. exit;
  155. if is_constintnode(p^.left) then
  156. begin
  157. t:=genordinalconstnode(-p^.left^.value,s32bitdef);
  158. disposetree(p);
  159. firstpass(t);
  160. p:=t;
  161. exit;
  162. end;
  163. { nasm can not cope with negativ reals !! }
  164. if is_constrealnode(p^.left)
  165. {$ifdef i386}
  166. and not(aktoutputformat in [as_i386_nasmcoff,as_i386_nasmelf,as_i386_nasmobj])
  167. {$endif i386}
  168. then
  169. begin
  170. t:=genrealconstnode(-p^.left^.value_real);
  171. disposetree(p);
  172. firstpass(t);
  173. p:=t;
  174. exit;
  175. end;
  176. if (p^.left^.resulttype^.deftype=floatdef) then
  177. begin
  178. if pfloatdef(p^.left^.resulttype)^.typ=f32bit then
  179. begin
  180. if (p^.left^.location.loc<>LOC_REGISTER) and
  181. (p^.registers32<1) then
  182. p^.registers32:=1;
  183. p^.location.loc:=LOC_REGISTER;
  184. end
  185. else
  186. p^.location.loc:=LOC_FPU;
  187. end
  188. {$ifdef SUPPORT_MMX}
  189. else if (cs_mmx in aktlocalswitches) and
  190. is_mmx_able_array(p^.left^.resulttype) then
  191. begin
  192. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  193. (p^.registersmmx<1) then
  194. p^.registersmmx:=1;
  195. { if saturation is on, p^.left^.resulttype isn't
  196. "mmx able" (FK)
  197. if (cs_mmx_saturation in aktlocalswitches^) and
  198. (porddef(parraydef(p^.resulttype)^.definition)^.typ in
  199. [s32bit,u32bit]) then
  200. CGMessage(type_e_mismatch);
  201. }
  202. end
  203. {$endif SUPPORT_MMX}
  204. else if is_64bitint(p^.left^.resulttype) then
  205. begin
  206. firstpass(p^.left);
  207. p^.registersfpu:=p^.left^.registersfpu;
  208. {$ifdef SUPPORT_MMX}
  209. p^.registersmmx:=p^.left^.registersmmx;
  210. {$endif SUPPORT_MMX}
  211. p^.registers32:=p^.left^.registers32;
  212. if codegenerror then
  213. exit;
  214. if (p^.left^.location.loc<>LOC_REGISTER) and
  215. (p^.registers32<2) then
  216. p^.registers32:=2;
  217. p^.location.loc:=LOC_REGISTER;
  218. p^.resulttype:=p^.left^.resulttype;
  219. end
  220. else if (p^.left^.resulttype^.deftype=orddef) then
  221. begin
  222. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  223. firstpass(p^.left);
  224. p^.registersfpu:=p^.left^.registersfpu;
  225. {$ifdef SUPPORT_MMX}
  226. p^.registersmmx:=p^.left^.registersmmx;
  227. {$endif SUPPORT_MMX}
  228. p^.registers32:=p^.left^.registers32;
  229. if codegenerror then
  230. exit;
  231. if (p^.left^.location.loc<>LOC_REGISTER) and
  232. (p^.registers32<1) then
  233. p^.registers32:=1;
  234. p^.location.loc:=LOC_REGISTER;
  235. p^.resulttype:=p^.left^.resulttype;
  236. end
  237. else
  238. begin
  239. if assigned(overloaded_operators[minus]) then
  240. minusdef:=overloaded_operators[minus]^.definition
  241. else
  242. minusdef:=nil;
  243. while assigned(minusdef) do
  244. begin
  245. if (minusdef^.para1^.data=p^.left^.resulttype) and
  246. (minusdef^.para1^.next=nil) then
  247. begin
  248. t:=gencallnode(overloaded_operators[minus],nil);
  249. t^.left:=gencallparanode(p^.left,nil);
  250. putnode(p);
  251. p:=t;
  252. firstpass(p);
  253. exit;
  254. end;
  255. minusdef:=minusdef^.nextoverloaded;
  256. end;
  257. CGMessage(type_e_mismatch);
  258. end;
  259. end;
  260. {*****************************************************************************
  261. FirstNot
  262. *****************************************************************************}
  263. procedure firstnot(var p : ptree);
  264. var
  265. t : ptree;
  266. begin
  267. firstpass(p^.left);
  268. if codegenerror then
  269. exit;
  270. if (p^.left^.treetype=ordconstn) then
  271. begin
  272. if is_boolean(p^.left^.resulttype) then
  273. t:=genordinalconstnode(byte(not(boolean(p^.left^.value))),p^.left^.resulttype)
  274. else
  275. t:=genordinalconstnode(not(p^.left^.value),p^.left^.resulttype);
  276. disposetree(p);
  277. firstpass(t);
  278. p:=t;
  279. exit;
  280. end;
  281. p^.resulttype:=p^.left^.resulttype;
  282. p^.location.loc:=p^.left^.location.loc;
  283. {$ifdef SUPPORT_MMX}
  284. p^.registersmmx:=p^.left^.registersmmx;
  285. {$endif SUPPORT_MMX}
  286. if is_boolean(p^.resulttype) then
  287. begin
  288. p^.registers32:=p^.left^.registers32;
  289. {$ifdef i386}
  290. if p^.left^.location.loc<>LOC_JUMP then
  291. p^.location.loc:=LOC_FLAGS;
  292. {$endif def i386}
  293. if (p^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  294. begin
  295. p^.location.loc:=LOC_REGISTER;
  296. if (p^.registers32<1) then
  297. p^.registers32:=1;
  298. end;
  299. end
  300. else
  301. {$ifdef SUPPORT_MMX}
  302. if (cs_mmx in aktlocalswitches) and
  303. is_mmx_able_array(p^.left^.resulttype) then
  304. begin
  305. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  306. (p^.registersmmx<1) then
  307. p^.registersmmx:=1;
  308. end
  309. else
  310. {$endif SUPPORT_MMX}
  311. if is_64bitint(p^.left^.resulttype) then
  312. begin
  313. p^.registers32:=p^.left^.registers32;
  314. if (p^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  315. begin
  316. p^.location.loc:=LOC_REGISTER;
  317. if (p^.registers32<2) then
  318. p^.registers32:=2;
  319. end;
  320. end
  321. else
  322. begin
  323. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  324. firstpass(p^.left);
  325. if codegenerror then
  326. exit;
  327. p^.resulttype:=p^.left^.resulttype;
  328. p^.registers32:=p^.left^.registers32;
  329. {$ifdef SUPPORT_MMX}
  330. p^.registersmmx:=p^.left^.registersmmx;
  331. {$endif SUPPORT_MMX}
  332. if (p^.left^.location.loc<>LOC_REGISTER) and
  333. (p^.registers32<1) then
  334. p^.registers32:=1;
  335. p^.location.loc:=LOC_REGISTER;
  336. end;
  337. p^.registersfpu:=p^.left^.registersfpu;
  338. end;
  339. end.
  340. {
  341. $Log$
  342. Revision 1.13 1999-05-01 13:24:55 peter
  343. * merged nasm compiler
  344. * old asm moved to oldasm/
  345. Revision 1.12 1999/02/22 02:15:53 peter
  346. * updates for ag386bin
  347. Revision 1.11 1999/02/03 10:11:11 pierre
  348. * fix for bug0211 for i386
  349. Revision 1.10 1998/12/11 16:50:24 florian
  350. + typed const int64 and qword
  351. + unary minus-operator q1:=-q2;
  352. + not-operator
  353. Revision 1.9 1998/12/11 16:10:12 florian
  354. + shifting for 64 bit ints added
  355. * bug in getexplicitregister32 fixed: usableregs wasn't decremented !!
  356. Revision 1.8 1998/12/11 00:03:56 peter
  357. + globtype,tokens,version unit splitted from globals
  358. Revision 1.7 1998/11/13 10:16:38 peter
  359. * fixed constant not(boolean)
  360. Revision 1.6 1998/11/05 14:26:01 peter
  361. * fixed shlshr which would push ecx when not needed
  362. Revision 1.5 1998/10/20 13:12:39 peter
  363. * fixed 'not not boolean', the location was not set to register
  364. Revision 1.4 1998/10/13 16:50:25 pierre
  365. * undid some changes of Peter that made the compiler wrong
  366. for m68k (I had to reinsert some ifdefs)
  367. * removed several memory leaks under m68k
  368. * removed the meory leaks for assembler readers
  369. * cross compiling shoud work again better
  370. ( crosscompiling sysamiga works
  371. but as68k still complain about some code !)
  372. Revision 1.3 1998/10/13 13:10:33 peter
  373. * new style for m68k/i386 infos and enums
  374. Revision 1.2 1998/10/11 14:31:20 peter
  375. + checks for division by zero
  376. Revision 1.1 1998/09/23 20:42:24 peter
  377. * splitted pass_1
  378. }