cg386add.pas 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for in add node
  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 cg386add;
  19. interface
  20. {$define usecreateset}
  21. uses
  22. tree;
  23. procedure secondadd(var p : ptree);
  24. implementation
  25. uses
  26. globtype,systems,
  27. cobjects,verbose,globals,
  28. symconst,symtable,aasm,types,
  29. hcodegen,temp_gen,pass_2,
  30. cpubase,cpuasm,
  31. cgai386,tgeni386;
  32. {*****************************************************************************
  33. Helpers
  34. *****************************************************************************}
  35. procedure locflags2reg(var l:tlocation;opsize:topsize);
  36. var
  37. hregister : tregister;
  38. begin
  39. if (l.loc=LOC_FLAGS) then
  40. begin
  41. case opsize of
  42. S_L : hregister:=getregister32;
  43. S_W : hregister:=reg32toreg16(getregister32);
  44. S_B : hregister:=reg32toreg8(getregister32);
  45. end;
  46. emit_flag2reg(l.resflags,hregister);
  47. l.loc:=LOC_REGISTER;
  48. l.register:=hregister;
  49. end;
  50. end;
  51. function getresflags(p : ptree;unsigned : boolean) : tresflags;
  52. begin
  53. if not(unsigned) then
  54. begin
  55. if p^.swaped then
  56. case p^.treetype of
  57. equaln : getresflags:=F_E;
  58. unequaln : getresflags:=F_NE;
  59. ltn : getresflags:=F_G;
  60. lten : getresflags:=F_GE;
  61. gtn : getresflags:=F_L;
  62. gten : getresflags:=F_LE;
  63. end
  64. else
  65. case p^.treetype of
  66. equaln : getresflags:=F_E;
  67. unequaln : getresflags:=F_NE;
  68. ltn : getresflags:=F_L;
  69. lten : getresflags:=F_LE;
  70. gtn : getresflags:=F_G;
  71. gten : getresflags:=F_GE;
  72. end;
  73. end
  74. else
  75. begin
  76. if p^.swaped then
  77. case p^.treetype of
  78. equaln : getresflags:=F_E;
  79. unequaln : getresflags:=F_NE;
  80. ltn : getresflags:=F_A;
  81. lten : getresflags:=F_AE;
  82. gtn : getresflags:=F_B;
  83. gten : getresflags:=F_BE;
  84. end
  85. else
  86. case p^.treetype of
  87. equaln : getresflags:=F_E;
  88. unequaln : getresflags:=F_NE;
  89. ltn : getresflags:=F_B;
  90. lten : getresflags:=F_BE;
  91. gtn : getresflags:=F_A;
  92. gten : getresflags:=F_AE;
  93. end;
  94. end;
  95. end;
  96. procedure SetResultLocation(cmpop,unsigned:boolean;var p :ptree);
  97. begin
  98. { remove temporary location if not a set or string }
  99. { that's a bad hack (FK) who did this ? }
  100. if (p^.left^.resulttype^.deftype<>stringdef) and
  101. ((p^.left^.resulttype^.deftype<>setdef) or (psetdef(p^.left^.resulttype)^.settype=smallset)) and
  102. (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  103. ungetiftemp(p^.left^.location.reference);
  104. if (p^.right^.resulttype^.deftype<>stringdef) and
  105. ((p^.right^.resulttype^.deftype<>setdef) or (psetdef(p^.right^.resulttype)^.settype=smallset)) and
  106. (p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  107. ungetiftemp(p^.right^.location.reference);
  108. { in case of comparison operation the put result in the flags }
  109. if cmpop then
  110. begin
  111. clear_location(p^.location);
  112. p^.location.loc:=LOC_FLAGS;
  113. p^.location.resflags:=getresflags(p,unsigned);
  114. end;
  115. end;
  116. {*****************************************************************************
  117. Addstring
  118. *****************************************************************************}
  119. procedure addstring(var p : ptree);
  120. var
  121. pushedregs : tpushed;
  122. href : treference;
  123. pushed,
  124. cmpop : boolean;
  125. begin
  126. { string operations are not commutative }
  127. if p^.swaped then
  128. swaptree(p);
  129. case pstringdef(p^.left^.resulttype)^.string_typ of
  130. st_ansistring:
  131. begin
  132. case p^.treetype of
  133. addn:
  134. begin
  135. cmpop:=false;
  136. secondpass(p^.left);
  137. { to avoid problem with maybe_push and restore }
  138. set_location(p^.location,p^.left^.location);
  139. pushed:=maybe_push(p^.right^.registers32,p,false);
  140. secondpass(p^.right);
  141. if pushed then
  142. begin
  143. restore(p,false);
  144. set_location(p^.left^.location,p^.location);
  145. end;
  146. { get the temp location, must be done before regs are
  147. released/pushed because after the release the regs are
  148. still used for the push (PFV) }
  149. clear_location(p^.location);
  150. p^.location.loc:=LOC_MEM;
  151. gettempansistringreference(p^.location.reference);
  152. decrstringref(cansistringdef,p^.location.reference);
  153. { release used registers }
  154. del_location(p^.right^.location);
  155. del_location(p^.left^.location);
  156. { push the still used registers }
  157. pushusedregisters(pushedregs,$ff);
  158. { push data }
  159. emitpushreferenceaddr(p^.location.reference);
  160. emit_push_loc(p^.right^.location);
  161. emit_push_loc(p^.left^.location);
  162. emitcall('FPC_ANSISTR_CONCAT');
  163. popusedregisters(pushedregs);
  164. maybe_loadesi;
  165. ungetiftempansi(p^.left^.location.reference);
  166. ungetiftempansi(p^.right^.location.reference);
  167. end;
  168. ltn,lten,gtn,gten,
  169. equaln,unequaln:
  170. begin
  171. cmpop:=true;
  172. secondpass(p^.left);
  173. pushed:=maybe_push(p^.right^.registers32,p^.left,false);
  174. secondpass(p^.right);
  175. if pushed then
  176. restore(p^.left,false);
  177. { release used registers }
  178. del_location(p^.right^.location);
  179. del_location(p^.left^.location);
  180. { push the still used registers }
  181. pushusedregisters(pushedregs,$ff);
  182. { push data }
  183. case p^.right^.location.loc of
  184. LOC_REFERENCE,LOC_MEM:
  185. emit_push_mem(p^.right^.location.reference);
  186. LOC_REGISTER,LOC_CREGISTER:
  187. emit_reg(A_PUSH,S_L,p^.right^.location.register);
  188. end;
  189. case p^.left^.location.loc of
  190. LOC_REFERENCE,LOC_MEM:
  191. emit_push_mem(p^.left^.location.reference);
  192. LOC_REGISTER,LOC_CREGISTER:
  193. emit_reg(A_PUSH,S_L,p^.left^.location.register);
  194. end;
  195. emitcall('FPC_ANSISTR_COMPARE');
  196. emit_reg_reg(A_OR,S_L,R_EAX,R_EAX);
  197. popusedregisters(pushedregs);
  198. maybe_loadesi;
  199. ungetiftempansi(p^.left^.location.reference);
  200. ungetiftempansi(p^.right^.location.reference);
  201. end;
  202. end;
  203. { the result of ansicompare is signed }
  204. SetResultLocation(cmpop,false,p);
  205. end;
  206. st_shortstring:
  207. begin
  208. case p^.treetype of
  209. addn:
  210. begin
  211. cmpop:=false;
  212. secondpass(p^.left);
  213. { if str_concat is set in expr
  214. s:=s+ ... no need to create a temp string (PM) }
  215. if (p^.left^.treetype<>addn) and not (p^.use_strconcat) then
  216. begin
  217. { can only reference be }
  218. { string in register would be funny }
  219. { therefore produce a temporary string }
  220. { release the registers }
  221. del_reference(p^.left^.location.reference);
  222. gettempofsizereference(256,href);
  223. copyshortstring(href,p^.left^.location.reference,255,false);
  224. ungetiftemp(p^.left^.location.reference);
  225. { does not hurt: }
  226. clear_location(p^.left^.location);
  227. p^.left^.location.loc:=LOC_MEM;
  228. p^.left^.location.reference:=href;
  229. end;
  230. secondpass(p^.right);
  231. { on the right we do not need the register anymore too }
  232. {$IfNDef regallocfix}
  233. del_reference(p^.right^.location.reference);
  234. pushusedregisters(pushedregs,$ff);
  235. {$Else regallocfix}
  236. pushusedregisters(pushedregs,$ff
  237. xor ($80 shr byte(p^.right^.location.reference.base))
  238. xor ($80 shr byte(p^.right^.location.reference.index)));
  239. {$EndIf regallocfix}
  240. emitpushreferenceaddr(p^.left^.location.reference);
  241. emitpushreferenceaddr(p^.right^.location.reference);
  242. {$IfDef regallocfix}
  243. del_reference(p^.right^.location.reference);
  244. {$EndIf regallocfix}
  245. emitcall('FPC_SHORTSTR_CONCAT');
  246. maybe_loadesi;
  247. popusedregisters(pushedregs);
  248. set_location(p^.location,p^.left^.location);
  249. ungetiftemp(p^.right^.location.reference);
  250. end;
  251. ltn,lten,gtn,gten,
  252. equaln,unequaln :
  253. begin
  254. cmpop:=true;
  255. { generate better code for s='' and s<>'' }
  256. if (p^.treetype in [equaln,unequaln]) and
  257. (((p^.left^.treetype=stringconstn) and (str_length(p^.left)=0)) or
  258. ((p^.right^.treetype=stringconstn) and (str_length(p^.right)=0))) then
  259. begin
  260. secondpass(p^.left);
  261. { are too few registers free? }
  262. pushed:=maybe_push(p^.right^.registers32,p^.left,false);
  263. secondpass(p^.right);
  264. if pushed then
  265. restore(p^.left,false);
  266. { only one node can be stringconstn }
  267. { else pass 1 would have evaluted }
  268. { this node }
  269. if p^.left^.treetype=stringconstn then
  270. emit_const_ref(
  271. A_CMP,S_B,0,newreference(p^.right^.location.reference))
  272. else
  273. emit_const_ref(
  274. A_CMP,S_B,0,newreference(p^.left^.location.reference));
  275. del_reference(p^.right^.location.reference);
  276. del_reference(p^.left^.location.reference);
  277. end
  278. else
  279. begin
  280. pushusedregisters(pushedregs,$ff);
  281. secondpass(p^.left);
  282. emitpushreferenceaddr(p^.left^.location.reference);
  283. del_reference(p^.left^.location.reference);
  284. secondpass(p^.right);
  285. emitpushreferenceaddr(p^.right^.location.reference);
  286. del_reference(p^.right^.location.reference);
  287. emitcall('FPC_SHORTSTR_COMPARE');
  288. maybe_loadesi;
  289. popusedregisters(pushedregs);
  290. end;
  291. ungetiftemp(p^.left^.location.reference);
  292. ungetiftemp(p^.right^.location.reference);
  293. end;
  294. else CGMessage(type_e_mismatch);
  295. end;
  296. SetResultLocation(cmpop,true,p);
  297. end;
  298. end;
  299. end;
  300. {*****************************************************************************
  301. Addset
  302. *****************************************************************************}
  303. procedure addset(var p : ptree);
  304. var
  305. createset,
  306. cmpop,
  307. pushed : boolean;
  308. href : treference;
  309. pushedregs : tpushed;
  310. begin
  311. cmpop:=false;
  312. { not commutative }
  313. if p^.swaped then
  314. swaptree(p);
  315. { optimize first loading of a set }
  316. {$ifdef usecreateset}
  317. if (p^.right^.treetype=setelementn) and
  318. not(assigned(p^.right^.right)) and
  319. is_emptyset(p^.left) then
  320. createset:=true
  321. else
  322. {$endif}
  323. begin
  324. createset:=false;
  325. secondpass(p^.left);
  326. end;
  327. { are too few registers free? }
  328. pushed:=maybe_push(p^.right^.registers32,p^.left,false);
  329. secondpass(p^.right);
  330. if codegenerror then
  331. exit;
  332. if pushed then
  333. restore(p^.left,false);
  334. set_location(p^.location,p^.left^.location);
  335. { handle operations }
  336. {$IfDef regallocfix}
  337. pushusedregisters(pushedregs,$ff
  338. xor ($80 shr byte(p^.left^.location.reference.base))
  339. xor ($80 shr byte(p^.left^.location.reference.index))
  340. xor ($80 shr byte(p^.right^.location.reference.base))
  341. xor ($80 shr byte(p^.right^.location.reference.index)));
  342. {$EndIf regallocfix}
  343. case p^.treetype of
  344. equaln,
  345. unequaln
  346. {$IfNDef NoSetInclusion}
  347. ,lten, gten
  348. {$EndIf NoSetInclusion}
  349. : begin
  350. cmpop:=true;
  351. del_location(p^.left^.location);
  352. del_location(p^.right^.location);
  353. pushusedregisters(pushedregs,$ff);
  354. {$IfNDef NoSetInclusion}
  355. If (p^.treetype in [equaln, unequaln, lten]) Then
  356. Begin
  357. {$EndIf NoSetInclusion}
  358. emitpushreferenceaddr(p^.right^.location.reference);
  359. emitpushreferenceaddr(p^.left^.location.reference);
  360. {$IfNDef NoSetInclusion}
  361. End
  362. Else {gten = lten, if the arguments are reversed}
  363. Begin
  364. emitpushreferenceaddr(p^.left^.location.reference);
  365. emitpushreferenceaddr(p^.right^.location.reference);
  366. End;
  367. Case p^.treetype of
  368. equaln, unequaln:
  369. {$EndIf NoSetInclusion}
  370. emitcall('FPC_SET_COMP_SETS');
  371. {$IfNDef NoSetInclusion}
  372. lten, gten:
  373. Begin
  374. emitcall('FPC_SET_CONTAINS_SETS');
  375. { we need a jne afterwards, not a jnbe/jnae }
  376. p^.treetype := equaln;
  377. End;
  378. End;
  379. {$EndIf NoSetInclusion}
  380. maybe_loadesi;
  381. popusedregisters(pushedregs);
  382. ungetiftemp(p^.left^.location.reference);
  383. ungetiftemp(p^.right^.location.reference);
  384. end;
  385. addn : begin
  386. { add can be an other SET or Range or Element ! }
  387. {$IfNDef regallocfix}
  388. del_location(p^.left^.location);
  389. { del_location(p^.right^.location);
  390. done in pushsetelement below PM }
  391. del_location(p^.right^.location);
  392. pushusedregisters(pushedregs,$ff);
  393. {$EndIf regallocfix}
  394. href.symbol:=nil;
  395. gettempofsizereference(32,href);
  396. if createset then
  397. begin
  398. {$IfDef regallocfix}
  399. del_location(p^.left^.location);
  400. { del_location(p^.right^.location);
  401. done in pushsetelement below PM }
  402. {$EndIf regallocfix}
  403. pushsetelement(p^.right^.left);
  404. emitpushreferenceaddr(href);
  405. emitcall('FPC_SET_CREATE_ELEMENT');
  406. end
  407. else
  408. begin
  409. { add a range or a single element? }
  410. if p^.right^.treetype=setelementn then
  411. begin
  412. {$IfNDef regallocfix}
  413. concatcopy(p^.left^.location.reference,href,32,false,false);
  414. {$Else regallocfix}
  415. concatcopy(p^.left^.location.reference,href,32,true,false);
  416. {$EndIf regallocfix}
  417. if assigned(p^.right^.right) then
  418. begin
  419. pushsetelement(p^.right^.right);
  420. pushsetelement(p^.right^.left);
  421. emitpushreferenceaddr(href);
  422. emitcall('FPC_SET_SET_RANGE');
  423. end
  424. else
  425. begin
  426. pushsetelement(p^.right^.left);
  427. emitpushreferenceaddr(href);
  428. emitcall('FPC_SET_SET_BYTE');
  429. end;
  430. end
  431. else
  432. begin
  433. { must be an other set }
  434. emitpushreferenceaddr(href);
  435. emitpushreferenceaddr(p^.right^.location.reference);
  436. {$IfDef regallocfix}
  437. del_location(p^.right^.location);
  438. {$EndIf regallocfix}
  439. emitpushreferenceaddr(p^.left^.location.reference);
  440. {$IfDef regallocfix}
  441. del_location(p^.left^.location);
  442. {$EndIf regallocfix}
  443. emitcall('FPC_SET_ADD_SETS');
  444. end;
  445. end;
  446. maybe_loadesi;
  447. popusedregisters(pushedregs);
  448. ungetiftemp(p^.left^.location.reference);
  449. ungetiftemp(p^.right^.location.reference);
  450. p^.location.loc:=LOC_MEM;
  451. p^.location.reference:=href;
  452. end;
  453. subn,
  454. symdifn,
  455. muln : begin
  456. {$IfNDef regallocfix}
  457. del_location(p^.left^.location);
  458. del_location(p^.right^.location);
  459. pushusedregisters(pushedregs,$ff);
  460. {$EndIf regallocfix}
  461. href.symbol:=nil;
  462. gettempofsizereference(32,href);
  463. emitpushreferenceaddr(href);
  464. emitpushreferenceaddr(p^.right^.location.reference);
  465. {$IfDef regallocfix}
  466. del_location(p^.right^.location);
  467. {$EndIf regallocfix}
  468. emitpushreferenceaddr(p^.left^.location.reference);
  469. {$IfDef regallocfix}
  470. del_location(p^.left^.location);
  471. {$EndIf regallocfix}
  472. case p^.treetype of
  473. subn : emitcall('FPC_SET_SUB_SETS');
  474. symdifn : emitcall('FPC_SET_SYMDIF_SETS');
  475. muln : emitcall('FPC_SET_MUL_SETS');
  476. end;
  477. maybe_loadesi;
  478. popusedregisters(pushedregs);
  479. ungetiftemp(p^.left^.location.reference);
  480. ungetiftemp(p^.right^.location.reference);
  481. p^.location.loc:=LOC_MEM;
  482. p^.location.reference:=href;
  483. end;
  484. else
  485. CGMessage(type_e_mismatch);
  486. end;
  487. SetResultLocation(cmpop,true,p);
  488. end;
  489. {*****************************************************************************
  490. SecondAdd
  491. *****************************************************************************}
  492. procedure secondadd(var p : ptree);
  493. { is also being used for xor, and "mul", "sub, or and comparative }
  494. { operators }
  495. label do_normal;
  496. var
  497. hregister,hregister2 : tregister;
  498. noswap,popeax,popedx,
  499. pushed,mboverflow,cmpop : boolean;
  500. op,op2 : tasmop;
  501. flags : tresflags;
  502. otl,ofl,hl : pasmlabel;
  503. power : longint;
  504. opsize : topsize;
  505. hl4: pasmlabel;
  506. hr : preference;
  507. { true, if unsigned types are compared }
  508. unsigned : boolean;
  509. { true, if a small set is handled with the longint code }
  510. is_set : boolean;
  511. { is_in_dest if the result is put directly into }
  512. { the resulting refernce or varregister }
  513. is_in_dest : boolean;
  514. { true, if for sets subtractions the extra not should generated }
  515. extra_not : boolean;
  516. {$ifdef SUPPORT_MMX}
  517. mmxbase : tmmxtype;
  518. {$endif SUPPORT_MMX}
  519. pushedreg : tpushed;
  520. hloc : tlocation;
  521. procedure firstjmp64bitcmp;
  522. var
  523. oldtreetype : ttreetyp;
  524. begin
  525. { the jump the sequence is a little bit hairy }
  526. case p^.treetype of
  527. ltn,gtn:
  528. begin
  529. emitjmp(flag_2_cond[getresflags(p,unsigned)],truelabel);
  530. { cheat a little bit for the negative test }
  531. p^.swaped:=not(p^.swaped);
  532. emitjmp(flag_2_cond[getresflags(p,unsigned)],falselabel);
  533. p^.swaped:=not(p^.swaped);
  534. end;
  535. lten,gten:
  536. begin
  537. oldtreetype:=p^.treetype;
  538. if p^.treetype=lten then
  539. p^.treetype:=ltn
  540. else
  541. p^.treetype:=gtn;
  542. emitjmp(flag_2_cond[getresflags(p,unsigned)],truelabel);
  543. { cheat for the negative test }
  544. if p^.treetype=ltn then
  545. p^.treetype:=gtn
  546. else
  547. p^.treetype:=ltn;
  548. emitjmp(flag_2_cond[getresflags(p,unsigned)],falselabel);
  549. p^.treetype:=oldtreetype;
  550. end;
  551. equaln:
  552. emitjmp(C_NE,falselabel);
  553. unequaln:
  554. emitjmp(C_NE,truelabel);
  555. end;
  556. end;
  557. procedure secondjmp64bitcmp;
  558. begin
  559. { the jump the sequence is a little bit hairy }
  560. case p^.treetype of
  561. ltn,gtn,lten,gten:
  562. begin
  563. { the comparisaion of the low dword have to be }
  564. { always unsigned! }
  565. emitjmp(flag_2_cond[getresflags(p,true)],truelabel);
  566. emitjmp(C_None,falselabel);
  567. end;
  568. equaln:
  569. begin
  570. emitjmp(C_NE,falselabel);
  571. emitjmp(C_None,truelabel);
  572. end;
  573. unequaln:
  574. begin
  575. emitjmp(C_NE,truelabel);
  576. emitjmp(C_None,falselabel);
  577. end;
  578. end;
  579. end;
  580. begin
  581. { to make it more readable, string and set (not smallset!) have their
  582. own procedures }
  583. case p^.left^.resulttype^.deftype of
  584. stringdef : begin
  585. addstring(p);
  586. exit;
  587. end;
  588. setdef : begin
  589. { normalsets are handled separate }
  590. if not(psetdef(p^.left^.resulttype)^.settype=smallset) then
  591. begin
  592. addset(p);
  593. exit;
  594. end;
  595. end;
  596. end;
  597. { defaults }
  598. unsigned:=false;
  599. is_in_dest:=false;
  600. extra_not:=false;
  601. noswap:=false;
  602. opsize:=S_L;
  603. { are we a (small)set, must be set here because the side can be
  604. swapped ! (PFV) }
  605. is_set:=(p^.left^.resulttype^.deftype=setdef);
  606. { calculate the operator which is more difficult }
  607. firstcomplex(p);
  608. { handling boolean expressions extra: }
  609. if is_boolean(p^.left^.resulttype) and
  610. is_boolean(p^.right^.resulttype) then
  611. begin
  612. if (porddef(p^.left^.resulttype)^.typ=bool8bit) or
  613. (porddef(p^.right^.resulttype)^.typ=bool8bit) then
  614. opsize:=S_B
  615. else
  616. if (porddef(p^.left^.resulttype)^.typ=bool16bit) or
  617. (porddef(p^.right^.resulttype)^.typ=bool16bit) then
  618. opsize:=S_W
  619. else
  620. opsize:=S_L;
  621. case p^.treetype of
  622. andn,
  623. orn : begin
  624. clear_location(p^.location);
  625. p^.location.loc:=LOC_JUMP;
  626. cmpop:=false;
  627. case p^.treetype of
  628. andn : begin
  629. otl:=truelabel;
  630. getlabel(truelabel);
  631. secondpass(p^.left);
  632. maketojumpbool(p^.left);
  633. emitlab(truelabel);
  634. truelabel:=otl;
  635. end;
  636. orn : begin
  637. ofl:=falselabel;
  638. getlabel(falselabel);
  639. secondpass(p^.left);
  640. maketojumpbool(p^.left);
  641. emitlab(falselabel);
  642. falselabel:=ofl;
  643. end;
  644. else
  645. CGMessage(type_e_mismatch);
  646. end;
  647. secondpass(p^.right);
  648. maketojumpbool(p^.right);
  649. end;
  650. unequaln,ltn,lten,gtn,gten,
  651. equaln,xorn : begin
  652. if p^.left^.treetype=ordconstn then
  653. swaptree(p);
  654. if p^.left^.location.loc=LOC_JUMP then
  655. begin
  656. otl:=truelabel;
  657. getlabel(truelabel);
  658. ofl:=falselabel;
  659. getlabel(falselabel);
  660. end;
  661. secondpass(p^.left);
  662. { if in flags then copy first to register, because the
  663. flags can be destroyed }
  664. case p^.left^.location.loc of
  665. LOC_FLAGS:
  666. locflags2reg(p^.left^.location,opsize);
  667. LOC_JUMP:
  668. begin
  669. case opsize of
  670. S_L : hregister:=getregister32;
  671. S_W : hregister:=reg32toreg16(getregister32);
  672. S_B : hregister:=reg32toreg8(getregister32);
  673. end;
  674. p^.left^.location.loc:=LOC_REGISTER;
  675. p^.left^.location.register:=hregister;
  676. emitlab(truelabel);
  677. truelabel:=otl;
  678. emit_const_reg(A_MOV,opsize,1,hregister);
  679. getlabel(hl);
  680. emitjmp(C_None,hl);
  681. emitlab(falselabel);
  682. falselabel:=ofl;
  683. emit_reg_reg(A_XOR,S_L,makereg32(hregister),
  684. makereg32(hregister));
  685. emitlab(hl);
  686. end;
  687. end;
  688. set_location(p^.location,p^.left^.location);
  689. pushed:=maybe_push(p^.right^.registers32,p,false);
  690. if p^.right^.location.loc=LOC_JUMP then
  691. begin
  692. otl:=truelabel;
  693. getlabel(truelabel);
  694. ofl:=falselabel;
  695. getlabel(falselabel);
  696. end;
  697. secondpass(p^.right);
  698. if pushed then
  699. begin
  700. restore(p,false);
  701. set_location(p^.left^.location,p^.location);
  702. end;
  703. case p^.right^.location.loc of
  704. LOC_FLAGS:
  705. locflags2reg(p^.right^.location,opsize);
  706. LOC_JUMP:
  707. begin
  708. case opsize of
  709. S_L : hregister:=getregister32;
  710. S_W : hregister:=reg32toreg16(getregister32);
  711. S_B : hregister:=reg32toreg8(getregister32);
  712. end;
  713. p^.right^.location.loc:=LOC_REGISTER;
  714. p^.right^.location.register:=hregister;
  715. emitlab(truelabel);
  716. truelabel:=otl;
  717. emit_const_reg(A_MOV,opsize,1,hregister);
  718. getlabel(hl);
  719. emitjmp(C_None,hl);
  720. emitlab(falselabel);
  721. falselabel:=ofl;
  722. emit_reg_reg(A_XOR,S_L,makereg32(hregister),
  723. makereg32(hregister));
  724. emitlab(hl);
  725. end;
  726. end;
  727. goto do_normal;
  728. end
  729. else
  730. CGMessage(type_e_mismatch);
  731. end
  732. end
  733. else
  734. begin
  735. { in case of constant put it to the left }
  736. if (p^.left^.treetype=ordconstn) then
  737. swaptree(p);
  738. secondpass(p^.left);
  739. { this will be complicated as
  740. a lot of code below assumes that
  741. p^.location and p^.left^.location are the same }
  742. {$ifdef test_dest_loc}
  743. if dest_loc_known and (dest_loc_tree=p) and
  744. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  745. begin
  746. set_location(p^.location,dest_loc);
  747. in_dest_loc:=true;
  748. is_in_dest:=true;
  749. end
  750. else
  751. {$endif test_dest_loc}
  752. set_location(p^.location,p^.left^.location);
  753. { are too few registers free? }
  754. pushed:=maybe_push(p^.right^.registers32,p,is_64bitint(p^.left^.resulttype));
  755. secondpass(p^.right);
  756. if pushed then
  757. begin
  758. restore(p,is_64bitint(p^.left^.resulttype));
  759. set_location(p^.left^.location,p^.location);
  760. end;
  761. if (p^.left^.resulttype^.deftype=pointerdef) or
  762. (p^.right^.resulttype^.deftype=pointerdef) or
  763. ((p^.right^.resulttype^.deftype=objectdef) and
  764. pobjectdef(p^.right^.resulttype)^.is_class and
  765. (p^.left^.resulttype^.deftype=objectdef) and
  766. pobjectdef(p^.left^.resulttype)^.is_class
  767. ) or
  768. (p^.left^.resulttype^.deftype=classrefdef) or
  769. (p^.left^.resulttype^.deftype=procvardef) or
  770. ((p^.left^.resulttype^.deftype=enumdef) and
  771. (p^.left^.resulttype^.size=4)) or
  772. ((p^.left^.resulttype^.deftype=orddef) and
  773. (porddef(p^.left^.resulttype)^.typ=s32bit)) or
  774. ((p^.right^.resulttype^.deftype=orddef) and
  775. (porddef(p^.right^.resulttype)^.typ=s32bit)) or
  776. ((p^.left^.resulttype^.deftype=orddef) and
  777. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  778. ((p^.right^.resulttype^.deftype=orddef) and
  779. (porddef(p^.right^.resulttype)^.typ=u32bit)) or
  780. { as well as small sets }
  781. is_set then
  782. begin
  783. do_normal:
  784. mboverflow:=false;
  785. cmpop:=false;
  786. {$ifndef cardinalmulfix}
  787. unsigned :=
  788. (p^.left^.resulttype^.deftype=pointerdef) or
  789. (p^.right^.resulttype^.deftype=pointerdef) or
  790. ((p^.left^.resulttype^.deftype=orddef) and
  791. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  792. ((p^.right^.resulttype^.deftype=orddef) and
  793. (porddef(p^.right^.resulttype)^.typ=u32bit));
  794. {$else cardinalmulfix}
  795. unsigned := not(is_signed(p^.left^.resulttype)) or
  796. not(is_signed(p^.right^.resulttype));
  797. {$endif cardinalmulfix}
  798. case p^.treetype of
  799. addn : begin
  800. if is_set then
  801. begin
  802. { adding elements is not commutative }
  803. if p^.swaped and (p^.left^.treetype=setelementn) then
  804. swaptree(p);
  805. { are we adding set elements ? }
  806. if p^.right^.treetype=setelementn then
  807. begin
  808. { no range support for smallsets! }
  809. if assigned(p^.right^.right) then
  810. internalerror(43244);
  811. { bts requires both elements to be registers }
  812. if p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  813. begin
  814. ungetiftemp(p^.left^.location.reference);
  815. del_location(p^.left^.location);
  816. {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  817. hregister:=getregister32;
  818. emit_ref_reg(A_MOV,opsize,
  819. newreference(p^.left^.location.reference),hregister);
  820. clear_location(p^.left^.location);
  821. p^.left^.location.loc:=LOC_REGISTER;
  822. p^.left^.location.register:=hregister;
  823. set_location(p^.location,p^.left^.location);
  824. end;
  825. if p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  826. begin
  827. ungetiftemp(p^.right^.location.reference);
  828. del_location(p^.right^.location);
  829. hregister:=getregister32;
  830. emit_ref_reg(A_MOV,opsize,
  831. newreference(p^.right^.location.reference),hregister);
  832. clear_location(p^.right^.location);
  833. p^.right^.location.loc:=LOC_REGISTER;
  834. p^.right^.location.register:=hregister;
  835. end;
  836. op:=A_BTS;
  837. noswap:=true;
  838. end
  839. else
  840. op:=A_OR;
  841. mboverflow:=false;
  842. unsigned:=false;
  843. end
  844. else
  845. begin
  846. op:=A_ADD;
  847. mboverflow:=true;
  848. end;
  849. end;
  850. symdifn : begin
  851. { the symetric diff is only for sets }
  852. if is_set then
  853. begin
  854. op:=A_XOR;
  855. mboverflow:=false;
  856. unsigned:=false;
  857. end
  858. else
  859. CGMessage(type_e_mismatch);
  860. end;
  861. muln : begin
  862. if is_set then
  863. begin
  864. op:=A_AND;
  865. mboverflow:=false;
  866. unsigned:=false;
  867. end
  868. else
  869. begin
  870. if unsigned then
  871. op:=A_MUL
  872. else
  873. op:=A_IMUL;
  874. mboverflow:=true;
  875. end;
  876. end;
  877. subn : begin
  878. if is_set then
  879. begin
  880. op:=A_AND;
  881. mboverflow:=false;
  882. unsigned:=false;
  883. {$IfNDef NoSetConstNot}
  884. If (p^.right^.treetype = setconstn) then
  885. p^.right^.location.reference.offset := not(p^.right^.location.reference.offset)
  886. Else
  887. {$EndIf NoNosetConstNot}
  888. extra_not:=true;
  889. end
  890. else
  891. begin
  892. op:=A_SUB;
  893. mboverflow:=true;
  894. end;
  895. end;
  896. ltn,lten,
  897. gtn,gten,
  898. equaln,unequaln : begin
  899. {$IfNDef NoSetInclusion}
  900. If is_set Then
  901. Case p^.treetype of
  902. lten,gten:
  903. Begin
  904. If p^.treetype = lten then
  905. swaptree(p);
  906. if p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  907. begin
  908. ungetiftemp(p^.left^.location.reference);
  909. del_reference(p^.left^.location.reference);
  910. hregister:=getregister32;
  911. emit_ref_reg(A_MOV,opsize,
  912. newreference(p^.left^.location.reference),hregister);
  913. clear_location(p^.left^.location);
  914. p^.left^.location.loc:=LOC_REGISTER;
  915. p^.left^.location.register:=hregister;
  916. set_location(p^.location,p^.left^.location);
  917. end
  918. else
  919. if p^.left^.location.loc = LOC_CREGISTER Then
  920. {save the register var in a temp register, because
  921. its value is going to be modified}
  922. begin
  923. hregister := getregister32;
  924. emit_reg_reg(A_MOV,opsize,
  925. p^.left^.location.register,hregister);
  926. clear_location(p^.left^.location);
  927. p^.left^.location.loc:=LOC_REGISTER;
  928. p^.left^.location.register:=hregister;
  929. set_location(p^.location,p^.left^.location);
  930. end;
  931. {here, p^.left^.location should be LOC_REGISTER}
  932. If p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE] Then
  933. emit_ref_reg(A_AND,opsize,
  934. newreference(p^.right^.location.reference),p^.left^.location.register)
  935. Else
  936. emit_reg_reg(A_AND,opsize,
  937. p^.right^.location.register,p^.left^.location.register);
  938. {warning: ugly hack ahead: we need a "jne" after the cmp, so
  939. change the treetype from lten/gten to equaln}
  940. p^.treetype := equaln
  941. End;
  942. {no < or > support for sets}
  943. ltn,gtn: CGMessage(type_e_mismatch);
  944. End;
  945. {$EndIf NoSetInclusion}
  946. op:=A_CMP;
  947. cmpop:=true;
  948. end;
  949. xorn : op:=A_XOR;
  950. orn : op:=A_OR;
  951. andn : op:=A_AND;
  952. else
  953. CGMessage(type_e_mismatch);
  954. end;
  955. { filter MUL, which requires special handling }
  956. if op=A_MUL then
  957. begin
  958. popeax:=false;
  959. popedx:=false;
  960. { here you need to free the symbol first }
  961. clear_location(p^.location);
  962. release_loc(p^.right^.location);
  963. release_loc(p^.left^.location);
  964. p^.location.register:=getregister32;
  965. p^.location.loc:=LOC_REGISTER;
  966. {$IfNDef NoShlMul}
  967. if p^.right^.treetype=ordconstn then
  968. swaptree(p);
  969. If (p^.left^.treetype = ordconstn) and
  970. ispowerof2(p^.left^.value, power) and
  971. not(cs_check_overflow in aktlocalswitches) then
  972. Begin
  973. emitloadord2reg(p^.right^.location,u32bitdef,p^.location.register,true);
  974. emit_const_reg(A_SHL,S_L,power,p^.location.register)
  975. End
  976. Else
  977. Begin
  978. {$EndIf NoShlMul}
  979. if not(R_EAX in unused) and (p^.location.register<>R_EAX) then
  980. begin
  981. emit_reg(A_PUSH,S_L,R_EAX);
  982. popeax:=true;
  983. end;
  984. if not(R_EDX in unused) and (p^.location.register<>R_EDX) then
  985. begin
  986. emit_reg(A_PUSH,S_L,R_EDX);
  987. popedx:=true;
  988. end;
  989. { p^.left^.location can be R_EAX !!! }
  990. emitloadord2reg(p^.left^.location,u32bitdef,R_EDI,true);
  991. emitloadord2reg(p^.right^.location,u32bitdef,R_EAX,true);
  992. emit_reg(A_MUL,S_L,R_EDI);
  993. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.register);
  994. if popedx then
  995. emit_reg(A_POP,S_L,R_EDX);
  996. if popeax then
  997. emit_reg(A_POP,S_L,R_EAX);
  998. {$IfNDef NoShlMul}
  999. End;
  1000. {$endif NoShlMul}
  1001. SetResultLocation(false,true,p);
  1002. exit;
  1003. end;
  1004. { Convert flags to register first }
  1005. if (p^.left^.location.loc=LOC_FLAGS) then
  1006. locflags2reg(p^.left^.location,opsize);
  1007. if (p^.right^.location.loc=LOC_FLAGS) then
  1008. locflags2reg(p^.right^.location,opsize);
  1009. { left and right no register? }
  1010. { then one must be demanded }
  1011. if (p^.left^.location.loc<>LOC_REGISTER) and
  1012. (p^.right^.location.loc<>LOC_REGISTER) then
  1013. begin
  1014. { register variable ? }
  1015. if (p^.left^.location.loc=LOC_CREGISTER) then
  1016. begin
  1017. { it is OK if this is the destination }
  1018. if is_in_dest then
  1019. begin
  1020. hregister:=p^.location.register;
  1021. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  1022. hregister);
  1023. end
  1024. else
  1025. if cmpop then
  1026. begin
  1027. { do not disturb the register }
  1028. hregister:=p^.location.register;
  1029. end
  1030. else
  1031. begin
  1032. case opsize of
  1033. S_L : hregister:=getregister32;
  1034. S_B : hregister:=reg32toreg8(getregister32);
  1035. end;
  1036. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  1037. hregister);
  1038. end
  1039. end
  1040. else
  1041. begin
  1042. ungetiftemp(p^.left^.location.reference);
  1043. del_reference(p^.left^.location.reference);
  1044. if is_in_dest then
  1045. begin
  1046. hregister:=p^.location.register;
  1047. emit_ref_reg(A_MOV,opsize,
  1048. newreference(p^.left^.location.reference),hregister);
  1049. end
  1050. else
  1051. begin
  1052. { first give free, then demand new register }
  1053. case opsize of
  1054. S_L : hregister:=getregister32;
  1055. S_W : hregister:=reg32toreg16(getregister32);
  1056. S_B : hregister:=reg32toreg8(getregister32);
  1057. end;
  1058. emit_ref_reg(A_MOV,opsize,
  1059. newreference(p^.left^.location.reference),hregister);
  1060. end;
  1061. end;
  1062. clear_location(p^.location);
  1063. p^.location.loc:=LOC_REGISTER;
  1064. p^.location.register:=hregister;
  1065. end
  1066. else
  1067. { if on the right the register then swap }
  1068. if not(noswap) and (p^.right^.location.loc=LOC_REGISTER) then
  1069. begin
  1070. swap_location(p^.location,p^.right^.location);
  1071. { newly swapped also set swapped flag }
  1072. p^.swaped:=not(p^.swaped);
  1073. end;
  1074. { at this point, p^.location.loc should be LOC_REGISTER }
  1075. { and p^.location.register should be a valid register }
  1076. { containing the left result }
  1077. if p^.right^.location.loc<>LOC_REGISTER then
  1078. begin
  1079. if (p^.treetype=subn) and p^.swaped then
  1080. begin
  1081. if p^.right^.location.loc=LOC_CREGISTER then
  1082. begin
  1083. if extra_not then
  1084. emit_reg(A_NOT,opsize,p^.location.register);
  1085. emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  1086. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  1087. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  1088. end
  1089. else
  1090. begin
  1091. if extra_not then
  1092. emit_reg(A_NOT,opsize,p^.location.register);
  1093. emit_ref_reg(A_MOV,opsize,
  1094. newreference(p^.right^.location.reference),R_EDI);
  1095. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  1096. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  1097. ungetiftemp(p^.right^.location.reference);
  1098. del_reference(p^.right^.location.reference);
  1099. end;
  1100. end
  1101. else
  1102. begin
  1103. if (p^.right^.treetype=ordconstn) and
  1104. (op=A_CMP) and
  1105. (p^.right^.value=0) then
  1106. begin
  1107. emit_reg_reg(A_TEST,opsize,p^.location.register,
  1108. p^.location.register);
  1109. end
  1110. else if (p^.right^.treetype=ordconstn) and
  1111. (op=A_ADD) and
  1112. (p^.right^.value=1) and
  1113. not(cs_check_overflow in aktlocalswitches) then
  1114. begin
  1115. emit_reg(A_INC,opsize,
  1116. p^.location.register);
  1117. end
  1118. else if (p^.right^.treetype=ordconstn) and
  1119. (op=A_SUB) and
  1120. (p^.right^.value=1) and
  1121. not(cs_check_overflow in aktlocalswitches) then
  1122. begin
  1123. emit_reg(A_DEC,opsize,
  1124. p^.location.register);
  1125. end
  1126. else if (p^.right^.treetype=ordconstn) and
  1127. (op=A_IMUL) and
  1128. (ispowerof2(p^.right^.value,power)) and
  1129. not(cs_check_overflow in aktlocalswitches) then
  1130. begin
  1131. emit_const_reg(A_SHL,opsize,power,
  1132. p^.location.register);
  1133. end
  1134. else
  1135. begin
  1136. if (p^.right^.location.loc=LOC_CREGISTER) then
  1137. begin
  1138. if extra_not then
  1139. begin
  1140. emit_reg_reg(A_MOV,S_L,p^.right^.location.register,R_EDI);
  1141. emit_reg(A_NOT,S_L,R_EDI);
  1142. emit_reg_reg(A_AND,S_L,R_EDI,
  1143. p^.location.register);
  1144. end
  1145. else
  1146. begin
  1147. emit_reg_reg(op,opsize,p^.right^.location.register,
  1148. p^.location.register);
  1149. end;
  1150. end
  1151. else
  1152. begin
  1153. if extra_not then
  1154. begin
  1155. emit_ref_reg(A_MOV,S_L,newreference(
  1156. p^.right^.location.reference),R_EDI);
  1157. emit_reg(A_NOT,S_L,R_EDI);
  1158. emit_reg_reg(A_AND,S_L,R_EDI,
  1159. p^.location.register);
  1160. end
  1161. else
  1162. begin
  1163. emit_ref_reg(op,opsize,newreference(
  1164. p^.right^.location.reference),p^.location.register);
  1165. end;
  1166. ungetiftemp(p^.right^.location.reference);
  1167. del_reference(p^.right^.location.reference);
  1168. end;
  1169. end;
  1170. end;
  1171. end
  1172. else
  1173. begin
  1174. { when swapped another result register }
  1175. if (p^.treetype=subn) and p^.swaped then
  1176. begin
  1177. if extra_not then
  1178. emit_reg(A_NOT,S_L,p^.location.register);
  1179. emit_reg_reg(op,opsize,
  1180. p^.location.register,p^.right^.location.register);
  1181. swap_location(p^.location,p^.right^.location);
  1182. { newly swapped also set swapped flag }
  1183. { just to maintain ordering }
  1184. p^.swaped:=not(p^.swaped);
  1185. end
  1186. else
  1187. begin
  1188. if extra_not then
  1189. emit_reg(A_NOT,S_L,p^.right^.location.register);
  1190. emit_reg_reg(op,opsize,
  1191. p^.right^.location.register,
  1192. p^.location.register);
  1193. end;
  1194. case opsize of
  1195. S_L : ungetregister32(p^.right^.location.register);
  1196. S_B : ungetregister32(reg8toreg32(p^.right^.location.register));
  1197. end;
  1198. end;
  1199. if cmpop then
  1200. case opsize of
  1201. S_L : ungetregister32(p^.location.register);
  1202. S_B : ungetregister32(reg8toreg32(p^.location.register));
  1203. end;
  1204. { only in case of overflow operations }
  1205. { produce overflow code }
  1206. { we must put it here directly, because sign of operation }
  1207. { is in unsigned VAR!! }
  1208. if mboverflow then
  1209. begin
  1210. if cs_check_overflow in aktlocalswitches then
  1211. begin
  1212. getlabel(hl4);
  1213. if unsigned then
  1214. emitjmp(C_NB,hl4)
  1215. else
  1216. emitjmp(C_NO,hl4);
  1217. emitcall('FPC_OVERFLOW');
  1218. emitlab(hl4);
  1219. end;
  1220. end;
  1221. end
  1222. else
  1223. { Char type }
  1224. if ((p^.left^.resulttype^.deftype=orddef) and
  1225. (porddef(p^.left^.resulttype)^.typ=uchar)) or
  1226. { enumeration type 16 bit }
  1227. ((p^.left^.resulttype^.deftype=enumdef) and
  1228. (p^.left^.resulttype^.size=1)) then
  1229. begin
  1230. case p^.treetype of
  1231. ltn,lten,gtn,gten,
  1232. equaln,unequaln :
  1233. cmpop:=true;
  1234. else CGMessage(type_e_mismatch);
  1235. end;
  1236. unsigned:=true;
  1237. { left and right no register? }
  1238. { the one must be demanded }
  1239. if (p^.location.loc<>LOC_REGISTER) and
  1240. (p^.right^.location.loc<>LOC_REGISTER) then
  1241. begin
  1242. if p^.location.loc=LOC_CREGISTER then
  1243. begin
  1244. if cmpop then
  1245. { do not disturb register }
  1246. hregister:=p^.location.register
  1247. else
  1248. begin
  1249. hregister:=reg32toreg8(getregister32);
  1250. emit_reg_reg(A_MOV,S_B,p^.location.register,
  1251. hregister);
  1252. end;
  1253. end
  1254. else
  1255. begin
  1256. del_reference(p^.location.reference);
  1257. { first give free then demand new register }
  1258. hregister:=reg32toreg8(getregister32);
  1259. emit_ref_reg(A_MOV,S_B,newreference(p^.location.reference),
  1260. hregister);
  1261. end;
  1262. clear_location(p^.location);
  1263. p^.location.loc:=LOC_REGISTER;
  1264. p^.location.register:=hregister;
  1265. end;
  1266. { now p always a register }
  1267. if (p^.right^.location.loc=LOC_REGISTER) and
  1268. (p^.location.loc<>LOC_REGISTER) then
  1269. begin
  1270. swap_location(p^.location,p^.right^.location);
  1271. { newly swapped also set swapped flag }
  1272. p^.swaped:=not(p^.swaped);
  1273. end;
  1274. if p^.right^.location.loc<>LOC_REGISTER then
  1275. begin
  1276. if p^.right^.location.loc=LOC_CREGISTER then
  1277. begin
  1278. emit_reg_reg(A_CMP,S_B,
  1279. p^.right^.location.register,p^.location.register);
  1280. end
  1281. else
  1282. begin
  1283. emit_ref_reg(A_CMP,S_B,newreference(
  1284. p^.right^.location.reference),p^.location.register);
  1285. del_reference(p^.right^.location.reference);
  1286. end;
  1287. end
  1288. else
  1289. begin
  1290. emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  1291. p^.location.register);
  1292. ungetregister32(reg8toreg32(p^.right^.location.register));
  1293. end;
  1294. ungetregister32(reg8toreg32(p^.location.register));
  1295. end
  1296. else
  1297. { 16 bit enumeration type }
  1298. if ((p^.left^.resulttype^.deftype=enumdef) and
  1299. (p^.left^.resulttype^.size=2)) then
  1300. begin
  1301. case p^.treetype of
  1302. ltn,lten,gtn,gten,
  1303. equaln,unequaln :
  1304. cmpop:=true;
  1305. else CGMessage(type_e_mismatch);
  1306. end;
  1307. unsigned:=true;
  1308. { left and right no register? }
  1309. { the one must be demanded }
  1310. if (p^.location.loc<>LOC_REGISTER) and
  1311. (p^.right^.location.loc<>LOC_REGISTER) then
  1312. begin
  1313. if p^.location.loc=LOC_CREGISTER then
  1314. begin
  1315. if cmpop then
  1316. { do not disturb register }
  1317. hregister:=p^.location.register
  1318. else
  1319. begin
  1320. hregister:=reg32toreg16(getregister32);
  1321. emit_reg_reg(A_MOV,S_W,p^.location.register,
  1322. hregister);
  1323. end;
  1324. end
  1325. else
  1326. begin
  1327. del_reference(p^.location.reference);
  1328. { first give free then demand new register }
  1329. hregister:=reg32toreg16(getregister32);
  1330. emit_ref_reg(A_MOV,S_W,newreference(p^.location.reference),
  1331. hregister);
  1332. end;
  1333. clear_location(p^.location);
  1334. p^.location.loc:=LOC_REGISTER;
  1335. p^.location.register:=hregister;
  1336. end;
  1337. { now p always a register }
  1338. if (p^.right^.location.loc=LOC_REGISTER) and
  1339. (p^.location.loc<>LOC_REGISTER) then
  1340. begin
  1341. swap_location(p^.location,p^.right^.location);
  1342. { newly swapped also set swapped flag }
  1343. p^.swaped:=not(p^.swaped);
  1344. end;
  1345. if p^.right^.location.loc<>LOC_REGISTER then
  1346. begin
  1347. if p^.right^.location.loc=LOC_CREGISTER then
  1348. begin
  1349. emit_reg_reg(A_CMP,S_W,
  1350. p^.right^.location.register,p^.location.register);
  1351. end
  1352. else
  1353. begin
  1354. emit_ref_reg(A_CMP,S_W,newreference(
  1355. p^.right^.location.reference),p^.location.register);
  1356. del_reference(p^.right^.location.reference);
  1357. end;
  1358. end
  1359. else
  1360. begin
  1361. emit_reg_reg(A_CMP,S_W,p^.right^.location.register,
  1362. p^.location.register);
  1363. ungetregister32(reg16toreg32(p^.right^.location.register));
  1364. end;
  1365. ungetregister32(reg16toreg32(p^.location.register));
  1366. end
  1367. else
  1368. { 64 bit types }
  1369. if is_64bitint(p^.left^.resulttype) then
  1370. begin
  1371. mboverflow:=false;
  1372. cmpop:=false;
  1373. unsigned:=((p^.left^.resulttype^.deftype=orddef) and
  1374. (porddef(p^.left^.resulttype)^.typ=u64bit)) or
  1375. ((p^.right^.resulttype^.deftype=orddef) and
  1376. (porddef(p^.right^.resulttype)^.typ=u64bit));
  1377. case p^.treetype of
  1378. addn : begin
  1379. begin
  1380. op:=A_ADD;
  1381. op2:=A_ADC;
  1382. mboverflow:=true;
  1383. end;
  1384. end;
  1385. subn : begin
  1386. op:=A_SUB;
  1387. op2:=A_SBB;
  1388. mboverflow:=true;
  1389. end;
  1390. ltn,lten,
  1391. gtn,gten,
  1392. equaln,unequaln:
  1393. begin
  1394. op:=A_CMP;
  1395. op2:=A_CMP;
  1396. cmpop:=true;
  1397. end;
  1398. xorn:
  1399. begin
  1400. op:=A_XOR;
  1401. op2:=A_XOR;
  1402. end;
  1403. orn:
  1404. begin
  1405. op:=A_OR;
  1406. op2:=A_OR;
  1407. end;
  1408. andn:
  1409. begin
  1410. op:=A_AND;
  1411. op2:=A_AND;
  1412. end;
  1413. muln:
  1414. ;
  1415. else
  1416. CGMessage(type_e_mismatch);
  1417. end;
  1418. if p^.treetype=muln then
  1419. begin
  1420. { save p^.lcoation, because we change it now }
  1421. set_location(hloc,p^.location);
  1422. release_qword_loc(p^.location);
  1423. release_qword_loc(p^.right^.location);
  1424. p^.location.registerlow:=getexplicitregister32(R_EAX);
  1425. p^.location.registerhigh:=getexplicitregister32(R_EDX);
  1426. pushusedregisters(pushedreg,$ff
  1427. and not($80 shr byte(p^.location.registerlow))
  1428. and not($80 shr byte(p^.location.registerhigh)));
  1429. if cs_check_overflow in aktlocalswitches then
  1430. push_int(1)
  1431. else
  1432. push_int(0);
  1433. { the left operand is in hloc, because the
  1434. location of left is p^.location but p^.location
  1435. is already destroyed
  1436. }
  1437. emit_pushq_loc(hloc);
  1438. clear_location(hloc);
  1439. emit_pushq_loc(p^.right^.location);
  1440. if porddef(p^.resulttype)^.typ=u64bit then
  1441. emitcall('FPC_MUL_QWORD')
  1442. else
  1443. emitcall('FPC_MUL_INT64');
  1444. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.registerlow);
  1445. emit_reg_reg(A_MOV,S_L,R_EDX,p^.location.registerhigh);
  1446. popusedregisters(pushedreg);
  1447. p^.location.loc:=LOC_REGISTER;
  1448. end
  1449. else
  1450. begin
  1451. { left and right no register? }
  1452. { then one must be demanded }
  1453. if (p^.left^.location.loc<>LOC_REGISTER) and
  1454. (p^.right^.location.loc<>LOC_REGISTER) then
  1455. begin
  1456. { register variable ? }
  1457. if (p^.left^.location.loc=LOC_CREGISTER) then
  1458. begin
  1459. { it is OK if this is the destination }
  1460. if is_in_dest then
  1461. begin
  1462. hregister:=p^.location.registerlow;
  1463. hregister2:=p^.location.registerhigh;
  1464. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  1465. hregister);
  1466. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  1467. hregister2);
  1468. end
  1469. else
  1470. if cmpop then
  1471. begin
  1472. { do not disturb the register }
  1473. hregister:=p^.location.registerlow;
  1474. hregister2:=p^.location.registerhigh;
  1475. end
  1476. else
  1477. begin
  1478. hregister:=getregister32;
  1479. hregister2:=getregister32;
  1480. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  1481. hregister);
  1482. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerhigh,
  1483. hregister2);
  1484. end
  1485. end
  1486. else
  1487. begin
  1488. ungetiftemp(p^.left^.location.reference);
  1489. del_reference(p^.left^.location.reference);
  1490. if is_in_dest then
  1491. begin
  1492. hregister:=p^.location.registerlow;
  1493. hregister2:=p^.location.registerhigh;
  1494. emit_ref_reg(A_MOV,S_L,
  1495. newreference(p^.left^.location.reference),hregister);
  1496. hr:=newreference(p^.left^.location.reference);
  1497. inc(hr^.offset,4);
  1498. emit_ref_reg(A_MOV,S_L,
  1499. hr,hregister2);
  1500. end
  1501. else
  1502. begin
  1503. hregister:=getregister32;
  1504. hregister2:=getregister32;
  1505. emit_ref_reg(A_MOV,S_L,
  1506. newreference(p^.left^.location.reference),hregister);
  1507. hr:=newreference(p^.left^.location.reference);
  1508. inc(hr^.offset,4);
  1509. emit_ref_reg(A_MOV,S_L,
  1510. hr,hregister2);
  1511. end;
  1512. end;
  1513. clear_location(p^.location);
  1514. p^.location.loc:=LOC_REGISTER;
  1515. p^.location.registerlow:=hregister;
  1516. p^.location.registerhigh:=hregister2;
  1517. end
  1518. else
  1519. { if on the right the register then swap }
  1520. if not(noswap) and (p^.right^.location.loc=LOC_REGISTER) then
  1521. begin
  1522. swap_location(p^.location,p^.right^.location);
  1523. { newly swapped also set swapped flag }
  1524. p^.swaped:=not(p^.swaped);
  1525. end;
  1526. { at this point, p^.location.loc should be LOC_REGISTER }
  1527. { and p^.location.register should be a valid register }
  1528. { containing the left result }
  1529. if p^.right^.location.loc<>LOC_REGISTER then
  1530. begin
  1531. if (p^.treetype=subn) and p^.swaped then
  1532. begin
  1533. if p^.right^.location.loc=LOC_CREGISTER then
  1534. begin
  1535. emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  1536. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  1537. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  1538. emit_reg_reg(A_MOV,opsize,p^.right^.location.registerhigh,R_EDI);
  1539. { the carry flag is still ok }
  1540. emit_reg_reg(op2,opsize,p^.location.registerhigh,R_EDI);
  1541. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.registerhigh);
  1542. end
  1543. else
  1544. begin
  1545. emit_ref_reg(A_MOV,opsize,
  1546. newreference(p^.right^.location.reference),R_EDI);
  1547. emit_reg_reg(op,opsize,p^.location.registerlow,R_EDI);
  1548. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.registerlow);
  1549. hr:=newreference(p^.right^.location.reference);
  1550. inc(hr^.offset,4);
  1551. emit_ref_reg(A_MOV,opsize,
  1552. hr,R_EDI);
  1553. { here the carry flag is still preserved }
  1554. emit_reg_reg(op2,opsize,p^.location.registerhigh,R_EDI);
  1555. emit_reg_reg(A_MOV,opsize,R_EDI,
  1556. p^.location.registerhigh);
  1557. ungetiftemp(p^.right^.location.reference);
  1558. del_reference(p^.right^.location.reference);
  1559. end;
  1560. end
  1561. else if cmpop then
  1562. begin
  1563. if (p^.right^.location.loc=LOC_CREGISTER) then
  1564. begin
  1565. emit_reg_reg(A_CMP,S_L,p^.right^.location.registerhigh,
  1566. p^.location.registerhigh);
  1567. firstjmp64bitcmp;
  1568. emit_reg_reg(A_CMP,S_L,p^.right^.location.registerlow,
  1569. p^.location.registerlow);
  1570. secondjmp64bitcmp;
  1571. end
  1572. else
  1573. begin
  1574. hr:=newreference(p^.right^.location.reference);
  1575. inc(hr^.offset,4);
  1576. emit_ref_reg(A_CMP,S_L,
  1577. hr,p^.location.registerhigh);
  1578. firstjmp64bitcmp;
  1579. emit_ref_reg(A_CMP,S_L,newreference(
  1580. p^.right^.location.reference),p^.location.registerlow);
  1581. secondjmp64bitcmp;
  1582. emitjmp(C_None,falselabel);
  1583. ungetiftemp(p^.right^.location.reference);
  1584. del_reference(p^.right^.location.reference);
  1585. end;
  1586. end
  1587. else
  1588. begin
  1589. {
  1590. if (p^.right^.treetype=ordconstn) and
  1591. (op=A_CMP) and
  1592. (p^.right^.value=0) then
  1593. begin
  1594. emit_reg_reg(A_TEST,opsize,p^.location.register,
  1595. p^.location.register);
  1596. end
  1597. else if (p^.right^.treetype=ordconstn) and
  1598. (op=A_IMUL) and
  1599. (ispowerof2(p^.right^.value,power)) then
  1600. begin
  1601. emit_const_reg(A_SHL,opsize,power,
  1602. p^.location.register);
  1603. end
  1604. else
  1605. }
  1606. begin
  1607. if (p^.right^.location.loc=LOC_CREGISTER) then
  1608. begin
  1609. emit_reg_reg(op,S_L,p^.right^.location.registerlow,
  1610. p^.location.registerlow);
  1611. emit_reg_reg(op2,S_L,p^.right^.location.registerhigh,
  1612. p^.location.registerhigh);
  1613. end
  1614. else
  1615. begin
  1616. emit_ref_reg(op,S_L,newreference(
  1617. p^.right^.location.reference),p^.location.registerlow);
  1618. hr:=newreference(p^.right^.location.reference);
  1619. inc(hr^.offset,4);
  1620. emit_ref_reg(op2,S_L,
  1621. hr,p^.location.registerhigh);
  1622. ungetiftemp(p^.right^.location.reference);
  1623. del_reference(p^.right^.location.reference);
  1624. end;
  1625. end;
  1626. end;
  1627. end
  1628. else
  1629. begin
  1630. { when swapped another result register }
  1631. if (p^.treetype=subn) and p^.swaped then
  1632. begin
  1633. emit_reg_reg(op,S_L,
  1634. p^.location.registerlow,
  1635. p^.right^.location.registerlow);
  1636. emit_reg_reg(op2,S_L,
  1637. p^.location.registerhigh,
  1638. p^.right^.location.registerhigh);
  1639. swap_location(p^.location,p^.right^.location);
  1640. { newly swapped also set swapped flag }
  1641. { just to maintain ordering }
  1642. p^.swaped:=not(p^.swaped);
  1643. end
  1644. else if cmpop then
  1645. begin
  1646. emit_reg_reg(A_CMP,S_L,
  1647. p^.right^.location.registerhigh,
  1648. p^.location.registerhigh);
  1649. firstjmp64bitcmp;
  1650. emit_reg_reg(A_CMP,S_L,
  1651. p^.right^.location.registerlow,
  1652. p^.location.registerlow);
  1653. secondjmp64bitcmp;
  1654. end
  1655. else
  1656. begin
  1657. emit_reg_reg(op,S_L,
  1658. p^.right^.location.registerlow,
  1659. p^.location.registerlow);
  1660. emit_reg_reg(op2,S_L,
  1661. p^.right^.location.registerhigh,
  1662. p^.location.registerhigh);
  1663. end;
  1664. ungetregister32(p^.right^.location.registerlow);
  1665. ungetregister32(p^.right^.location.registerhigh);
  1666. end;
  1667. if cmpop then
  1668. begin
  1669. ungetregister32(p^.location.registerlow);
  1670. ungetregister32(p^.location.registerhigh);
  1671. end;
  1672. { only in case of overflow operations }
  1673. { produce overflow code }
  1674. { we must put it here directly, because sign of operation }
  1675. { is in unsigned VAR!! }
  1676. if mboverflow then
  1677. begin
  1678. if cs_check_overflow in aktlocalswitches then
  1679. begin
  1680. getlabel(hl4);
  1681. if unsigned then
  1682. emitjmp(C_NB,hl4)
  1683. else
  1684. emitjmp(C_NO,hl4);
  1685. emitcall('FPC_OVERFLOW');
  1686. emitlab(hl4);
  1687. end;
  1688. end;
  1689. { we have LOC_JUMP as result }
  1690. if cmpop then
  1691. begin
  1692. clear_location(p^.location);
  1693. p^.location.loc:=LOC_JUMP;
  1694. cmpop:=false;
  1695. end;
  1696. end;
  1697. end
  1698. else
  1699. { Floating point }
  1700. if (p^.left^.resulttype^.deftype=floatdef) and
  1701. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  1702. begin
  1703. { real constants to the right, but only if it
  1704. isn't on the FPU stack, i.e. 1.0 or 0.0! }
  1705. if (p^.left^.treetype=realconstn) and
  1706. (p^.left^.location.loc<>LOC_FPU) then
  1707. swaptree(p);
  1708. cmpop:=false;
  1709. case p^.treetype of
  1710. addn : op:=A_FADDP;
  1711. muln : op:=A_FMULP;
  1712. subn : op:=A_FSUBP;
  1713. slashn : op:=A_FDIVP;
  1714. ltn,lten,gtn,gten,
  1715. equaln,unequaln : begin
  1716. op:=A_FCOMPP;
  1717. cmpop:=true;
  1718. end;
  1719. else CGMessage(type_e_mismatch);
  1720. end;
  1721. if (p^.right^.location.loc<>LOC_FPU) then
  1722. begin
  1723. if p^.right^.location.loc=LOC_CFPUREGISTER then
  1724. begin
  1725. emit_reg( A_FLD,S_NO,
  1726. correct_fpuregister(p^.right^.location.register,fpuvaroffset));
  1727. inc(fpuvaroffset);
  1728. end
  1729. else
  1730. floatload(pfloatdef(p^.right^.resulttype)^.typ,p^.right^.location.reference);
  1731. if (p^.left^.location.loc<>LOC_FPU) then
  1732. begin
  1733. if p^.left^.location.loc=LOC_CFPUREGISTER then
  1734. begin
  1735. emit_reg( A_FLD,S_NO,
  1736. correct_fpuregister(p^.left^.location.register,fpuvaroffset));
  1737. inc(fpuvaroffset);
  1738. end
  1739. else
  1740. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  1741. end
  1742. { left was on the stack => swap }
  1743. else
  1744. p^.swaped:=not(p^.swaped);
  1745. { releases the right reference }
  1746. del_reference(p^.right^.location.reference);
  1747. end
  1748. { the nominator in st0 }
  1749. else if (p^.left^.location.loc<>LOC_FPU) then
  1750. begin
  1751. if p^.left^.location.loc=LOC_CFPUREGISTER then
  1752. begin
  1753. emit_reg( A_FLD,S_NO,
  1754. correct_fpuregister(p^.left^.location.register,fpuvaroffset));
  1755. inc(fpuvaroffset);
  1756. end
  1757. else
  1758. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  1759. end
  1760. { fpu operands are always in the wrong order on the stack }
  1761. else
  1762. p^.swaped:=not(p^.swaped);
  1763. { releases the left reference }
  1764. if (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  1765. del_reference(p^.left^.location.reference);
  1766. { if we swaped the tree nodes, then use the reverse operator }
  1767. if p^.swaped then
  1768. begin
  1769. if (p^.treetype=slashn) then
  1770. op:=A_FDIVRP
  1771. else if (p^.treetype=subn) then
  1772. op:=A_FSUBRP;
  1773. end;
  1774. { to avoid the pentium bug
  1775. if (op=FDIVP) and (opt_processors=pentium) then
  1776. emitcall('EMUL_FDIVP')
  1777. else
  1778. }
  1779. { the Intel assemblers want operands }
  1780. if op<>A_FCOMPP then
  1781. begin
  1782. emit_reg_reg(op,S_NO,R_ST,R_ST1);
  1783. dec(fpuvaroffset);
  1784. end
  1785. else
  1786. begin
  1787. emit_none(op,S_NO);
  1788. dec(fpuvaroffset,2);
  1789. end;
  1790. { on comparison load flags }
  1791. if cmpop then
  1792. begin
  1793. if not(R_EAX in unused) then
  1794. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  1795. emit_reg(A_FNSTSW,S_NO,R_AX);
  1796. emit_none(A_SAHF,S_NO);
  1797. if not(R_EAX in unused) then
  1798. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  1799. if p^.swaped then
  1800. begin
  1801. case p^.treetype of
  1802. equaln : flags:=F_E;
  1803. unequaln : flags:=F_NE;
  1804. ltn : flags:=F_A;
  1805. lten : flags:=F_AE;
  1806. gtn : flags:=F_B;
  1807. gten : flags:=F_BE;
  1808. end;
  1809. end
  1810. else
  1811. begin
  1812. case p^.treetype of
  1813. equaln : flags:=F_E;
  1814. unequaln : flags:=F_NE;
  1815. ltn : flags:=F_B;
  1816. lten : flags:=F_BE;
  1817. gtn : flags:=F_A;
  1818. gten : flags:=F_AE;
  1819. end;
  1820. end;
  1821. clear_location(p^.location);
  1822. p^.location.loc:=LOC_FLAGS;
  1823. p^.location.resflags:=flags;
  1824. cmpop:=false;
  1825. end
  1826. else
  1827. begin
  1828. clear_location(p^.location);
  1829. p^.location.loc:=LOC_FPU;
  1830. end;
  1831. end
  1832. {$ifdef SUPPORT_MMX}
  1833. else
  1834. { MMX Arrays }
  1835. if is_mmx_able_array(p^.left^.resulttype) then
  1836. begin
  1837. cmpop:=false;
  1838. mmxbase:=mmx_type(p^.left^.resulttype);
  1839. case p^.treetype of
  1840. addn : begin
  1841. if (cs_mmx_saturation in aktlocalswitches) then
  1842. begin
  1843. case mmxbase of
  1844. mmxs8bit:
  1845. op:=A_PADDSB;
  1846. mmxu8bit:
  1847. op:=A_PADDUSB;
  1848. mmxs16bit,mmxfixed16:
  1849. op:=A_PADDSB;
  1850. mmxu16bit:
  1851. op:=A_PADDUSW;
  1852. end;
  1853. end
  1854. else
  1855. begin
  1856. case mmxbase of
  1857. mmxs8bit,mmxu8bit:
  1858. op:=A_PADDB;
  1859. mmxs16bit,mmxu16bit,mmxfixed16:
  1860. op:=A_PADDW;
  1861. mmxs32bit,mmxu32bit:
  1862. op:=A_PADDD;
  1863. end;
  1864. end;
  1865. end;
  1866. muln : begin
  1867. case mmxbase of
  1868. mmxs16bit,mmxu16bit:
  1869. op:=A_PMULLW;
  1870. mmxfixed16:
  1871. op:=A_PMULHW;
  1872. end;
  1873. end;
  1874. subn : begin
  1875. if (cs_mmx_saturation in aktlocalswitches) then
  1876. begin
  1877. case mmxbase of
  1878. mmxs8bit:
  1879. op:=A_PSUBSB;
  1880. mmxu8bit:
  1881. op:=A_PSUBUSB;
  1882. mmxs16bit,mmxfixed16:
  1883. op:=A_PSUBSB;
  1884. mmxu16bit:
  1885. op:=A_PSUBUSW;
  1886. end;
  1887. end
  1888. else
  1889. begin
  1890. case mmxbase of
  1891. mmxs8bit,mmxu8bit:
  1892. op:=A_PSUBB;
  1893. mmxs16bit,mmxu16bit,mmxfixed16:
  1894. op:=A_PSUBW;
  1895. mmxs32bit,mmxu32bit:
  1896. op:=A_PSUBD;
  1897. end;
  1898. end;
  1899. end;
  1900. {
  1901. ltn,lten,gtn,gten,
  1902. equaln,unequaln :
  1903. begin
  1904. op:=A_CMP;
  1905. cmpop:=true;
  1906. end;
  1907. }
  1908. xorn:
  1909. op:=A_PXOR;
  1910. orn:
  1911. op:=A_POR;
  1912. andn:
  1913. op:=A_PAND;
  1914. else CGMessage(type_e_mismatch);
  1915. end;
  1916. { left and right no register? }
  1917. { then one must be demanded }
  1918. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  1919. (p^.right^.location.loc<>LOC_MMXREGISTER) then
  1920. begin
  1921. { register variable ? }
  1922. if (p^.left^.location.loc=LOC_CMMXREGISTER) then
  1923. begin
  1924. { it is OK if this is the destination }
  1925. if is_in_dest then
  1926. begin
  1927. hregister:=p^.location.register;
  1928. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1929. hregister);
  1930. end
  1931. else
  1932. begin
  1933. hregister:=getregistermmx;
  1934. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1935. hregister);
  1936. end
  1937. end
  1938. else
  1939. begin
  1940. del_reference(p^.left^.location.reference);
  1941. if is_in_dest then
  1942. begin
  1943. hregister:=p^.location.register;
  1944. emit_ref_reg(A_MOVQ,S_NO,
  1945. newreference(p^.left^.location.reference),hregister);
  1946. end
  1947. else
  1948. begin
  1949. hregister:=getregistermmx;
  1950. emit_ref_reg(A_MOVQ,S_NO,
  1951. newreference(p^.left^.location.reference),hregister);
  1952. end;
  1953. end;
  1954. clear_location(p^.location);
  1955. p^.location.loc:=LOC_MMXREGISTER;
  1956. p^.location.register:=hregister;
  1957. end
  1958. else
  1959. { if on the right the register then swap }
  1960. if (p^.right^.location.loc=LOC_MMXREGISTER) then
  1961. begin
  1962. swap_location(p^.location,p^.right^.location);
  1963. { newly swapped also set swapped flag }
  1964. p^.swaped:=not(p^.swaped);
  1965. end;
  1966. { at this point, p^.location.loc should be LOC_MMXREGISTER }
  1967. { and p^.location.register should be a valid register }
  1968. { containing the left result }
  1969. if p^.right^.location.loc<>LOC_MMXREGISTER then
  1970. begin
  1971. if (p^.treetype=subn) and p^.swaped then
  1972. begin
  1973. if p^.right^.location.loc=LOC_CMMXREGISTER then
  1974. begin
  1975. emit_reg_reg(A_MOVQ,S_NO,p^.right^.location.register,R_MM7);
  1976. emit_reg_reg(op,S_NO,p^.location.register,R_EDI);
  1977. emit_reg_reg(A_MOVQ,S_NO,R_MM7,p^.location.register);
  1978. end
  1979. else
  1980. begin
  1981. emit_ref_reg(A_MOVQ,S_NO,
  1982. newreference(p^.right^.location.reference),R_MM7);
  1983. emit_reg_reg(op,S_NO,p^.location.register,
  1984. R_MM7);
  1985. emit_reg_reg(A_MOVQ,S_NO,
  1986. R_MM7,p^.location.register);
  1987. del_reference(p^.right^.location.reference);
  1988. end;
  1989. end
  1990. else
  1991. begin
  1992. if (p^.right^.location.loc=LOC_CREGISTER) then
  1993. begin
  1994. emit_reg_reg(op,S_NO,p^.right^.location.register,
  1995. p^.location.register);
  1996. end
  1997. else
  1998. begin
  1999. emit_ref_reg(op,S_NO,newreference(
  2000. p^.right^.location.reference),p^.location.register);
  2001. del_reference(p^.right^.location.reference);
  2002. end;
  2003. end;
  2004. end
  2005. else
  2006. begin
  2007. { when swapped another result register }
  2008. if (p^.treetype=subn) and p^.swaped then
  2009. begin
  2010. emit_reg_reg(op,S_NO,
  2011. p^.location.register,p^.right^.location.register);
  2012. swap_location(p^.location,p^.right^.location);
  2013. { newly swapped also set swapped flag }
  2014. { just to maintain ordering }
  2015. p^.swaped:=not(p^.swaped);
  2016. end
  2017. else
  2018. begin
  2019. emit_reg_reg(op,S_NO,
  2020. p^.right^.location.register,
  2021. p^.location.register);
  2022. end;
  2023. ungetregistermmx(p^.right^.location.register);
  2024. end;
  2025. end
  2026. {$endif SUPPORT_MMX}
  2027. else CGMessage(type_e_mismatch);
  2028. end;
  2029. SetResultLocation(cmpop,unsigned,p);
  2030. end;
  2031. end.
  2032. {
  2033. $Log$
  2034. Revision 1.84 2000-01-07 01:14:20 peter
  2035. * updated copyright to 2000
  2036. Revision 1.83 1999/12/11 18:53:31 jonas
  2037. * fixed type conversions of results of operations with cardinals
  2038. (between -dcardinalmulfix)
  2039. Revision 1.82 1999/11/06 14:34:17 peter
  2040. * truncated log to 20 revs
  2041. Revision 1.81 1999/09/28 19:43:45 florian
  2042. * the maybe_push fix of Pierre wasn't 100%, the tree parameter
  2043. must contain a valid location (which is saved if necessary)
  2044. Revision 1.80 1999/09/26 13:26:01 florian
  2045. * exception patch of Romio nevertheless the excpetion handling
  2046. needs some corections regarding register saving
  2047. * gettempansistring is again a procedure
  2048. Revision 1.79 1999/09/21 20:53:21 florian
  2049. * fixed 1/s problem from mailing list
  2050. Revision 1.78 1999/09/07 07:52:19 peter
  2051. * > < >= <= support for boolean
  2052. * boolean constants are now calculated like integer constants
  2053. Revision 1.77 1999/08/30 12:00:45 pierre
  2054. * problem with maybe_push/restore solved hopefully
  2055. Revision 1.76 1999/08/23 23:31:00 pierre
  2056. * double del_location removed in add_set
  2057. Revision 1.75 1999/08/23 10:35:13 jonas
  2058. * fixed <= and >= for sets
  2059. Revision 1.74 1999/08/19 13:08:43 pierre
  2060. * emit_??? used
  2061. Revision 1.73 1999/08/07 11:29:26 peter
  2062. * better fix for muln register allocation
  2063. Revision 1.72 1999/08/04 13:45:17 florian
  2064. + floating point register variables !!
  2065. * pairegalloc is now generated for register variables
  2066. Revision 1.71 1999/08/04 00:22:40 florian
  2067. * renamed i386asm and i386base to cpuasm and cpubase
  2068. Revision 1.70 1999/08/03 22:02:31 peter
  2069. * moved bitmask constants to sets
  2070. * some other type/const renamings
  2071. Revision 1.69 1999/07/05 20:13:06 peter
  2072. * removed temp defines
  2073. Revision 1.68 1999/07/02 12:18:46 jonas
  2074. * released setconstnot (changed to $ifndef nosetconstnot)
  2075. * released shlmul (changed to $ifndef no shlmul)
  2076. Revision 1.67 1999/06/14 17:47:45 peter
  2077. * merged
  2078. Revision 1.66.2.1 1999/06/14 17:24:40 peter
  2079. * fixed saving of registers with decr_ansistr
  2080. Revision 1.66 1999/06/09 23:22:37 peter
  2081. + del_location
  2082. Revision 1.65 1999/06/09 23:00:11 peter
  2083. * small ansistring fixes
  2084. * val_ansistr_sint destsize changed to longint
  2085. * don't write low/hi ascii with -al
  2086. Revision 1.64 1999/06/02 10:11:39 florian
  2087. * make cycle fixed i.e. compilation with 0.99.10
  2088. * some fixes for qword
  2089. * start of register calling conventions
  2090. Revision 1.63 1999/05/31 20:35:45 peter
  2091. * ansistring fixes, decr_ansistr called after all temp ansi reuses
  2092. }