cg386add.pas 107 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353
  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. gettempofsizereference(256,href);
  221. copyshortstring(href,p^.left^.location.reference,255,false);
  222. { release the registers }
  223. del_reference(p^.left^.location.reference);
  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. regstopush: byte;
  311. begin
  312. cmpop:=false;
  313. { not commutative }
  314. if p^.swaped then
  315. swaptree(p);
  316. { optimize first loading of a set }
  317. {$ifdef usecreateset}
  318. if (p^.right^.treetype=setelementn) and
  319. not(assigned(p^.right^.right)) and
  320. is_emptyset(p^.left) then
  321. createset:=true
  322. else
  323. {$endif}
  324. begin
  325. createset:=false;
  326. secondpass(p^.left);
  327. end;
  328. { are too few registers free? }
  329. pushed:=maybe_push(p^.right^.registers32,p^.left,false);
  330. secondpass(p^.right);
  331. if codegenerror then
  332. exit;
  333. if pushed then
  334. restore(p^.left,false);
  335. set_location(p^.location,p^.left^.location);
  336. { handle operations }
  337. case p^.treetype of
  338. equaln,
  339. unequaln
  340. {$IfNDef NoSetInclusion}
  341. ,lten, gten
  342. {$EndIf NoSetInclusion}
  343. : begin
  344. cmpop:=true;
  345. del_location(p^.left^.location);
  346. del_location(p^.right^.location);
  347. pushusedregisters(pushedregs,$ff);
  348. {$IfNDef NoSetInclusion}
  349. If (p^.treetype in [equaln, unequaln, lten]) Then
  350. Begin
  351. {$EndIf NoSetInclusion}
  352. emitpushreferenceaddr(p^.right^.location.reference);
  353. emitpushreferenceaddr(p^.left^.location.reference);
  354. {$IfNDef NoSetInclusion}
  355. End
  356. Else {gten = lten, if the arguments are reversed}
  357. Begin
  358. emitpushreferenceaddr(p^.left^.location.reference);
  359. emitpushreferenceaddr(p^.right^.location.reference);
  360. End;
  361. Case p^.treetype of
  362. equaln, unequaln:
  363. {$EndIf NoSetInclusion}
  364. emitcall('FPC_SET_COMP_SETS');
  365. {$IfNDef NoSetInclusion}
  366. lten, gten:
  367. Begin
  368. emitcall('FPC_SET_CONTAINS_SETS');
  369. { we need a jne afterwards, not a jnbe/jnae }
  370. p^.treetype := equaln;
  371. End;
  372. End;
  373. {$EndIf NoSetInclusion}
  374. maybe_loadesi;
  375. popusedregisters(pushedregs);
  376. ungetiftemp(p^.left^.location.reference);
  377. ungetiftemp(p^.right^.location.reference);
  378. end;
  379. addn : begin
  380. { add can be an other SET or Range or Element ! }
  381. { del_location(p^.right^.location);
  382. done in pushsetelement below PM
  383. And someone added it again because those registers must
  384. not be pushed by the pushusedregisters, however this
  385. breaks the optimizer (JM)
  386. del_location(p^.right^.location);
  387. pushusedregisters(pushedregs,$ff);}
  388. regstopush := $ff;
  389. remove_non_regvars_from_loc(p^.right^.location,regstopush);
  390. remove_non_regvars_from_loc(p^.left^.location,regstopush);
  391. pushusedregisters(pushedregs,regstopush);
  392. { this is still right before the instruction that uses }
  393. { p^.left^.location, but that can be fixed by the }
  394. { optimizer. There must never be an additional }
  395. { between the release and the use, because that is not }
  396. { detected/fixed. As Pierre said above, p^.right^.loc }
  397. { will be released in pushsetelement (JM) }
  398. del_location(p^.left^.location);
  399. href.symbol:=nil;
  400. gettempofsizereference(32,href);
  401. if createset then
  402. begin
  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. regstopush: byte;
  522. procedure firstjmp64bitcmp;
  523. var
  524. oldtreetype : ttreetyp;
  525. begin
  526. { the jump the sequence is a little bit hairy }
  527. case p^.treetype of
  528. ltn,gtn:
  529. begin
  530. emitjmp(flag_2_cond[getresflags(p,unsigned)],truelabel);
  531. { cheat a little bit for the negative test }
  532. p^.swaped:=not(p^.swaped);
  533. emitjmp(flag_2_cond[getresflags(p,unsigned)],falselabel);
  534. p^.swaped:=not(p^.swaped);
  535. end;
  536. lten,gten:
  537. begin
  538. oldtreetype:=p^.treetype;
  539. if p^.treetype=lten then
  540. p^.treetype:=ltn
  541. else
  542. p^.treetype:=gtn;
  543. emitjmp(flag_2_cond[getresflags(p,unsigned)],truelabel);
  544. { cheat for the negative test }
  545. if p^.treetype=ltn then
  546. p^.treetype:=gtn
  547. else
  548. p^.treetype:=ltn;
  549. emitjmp(flag_2_cond[getresflags(p,unsigned)],falselabel);
  550. p^.treetype:=oldtreetype;
  551. end;
  552. equaln:
  553. emitjmp(C_NE,falselabel);
  554. unequaln:
  555. emitjmp(C_NE,truelabel);
  556. end;
  557. end;
  558. procedure secondjmp64bitcmp;
  559. begin
  560. { the jump the sequence is a little bit hairy }
  561. case p^.treetype of
  562. ltn,gtn,lten,gten:
  563. begin
  564. { the comparisaion of the low dword have to be }
  565. { always unsigned! }
  566. emitjmp(flag_2_cond[getresflags(p,true)],truelabel);
  567. emitjmp(C_None,falselabel);
  568. end;
  569. equaln:
  570. begin
  571. emitjmp(C_NE,falselabel);
  572. emitjmp(C_None,truelabel);
  573. end;
  574. unequaln:
  575. begin
  576. emitjmp(C_NE,truelabel);
  577. emitjmp(C_None,falselabel);
  578. end;
  579. end;
  580. end;
  581. begin
  582. { to make it more readable, string and set (not smallset!) have their
  583. own procedures }
  584. case p^.left^.resulttype^.deftype of
  585. stringdef : begin
  586. addstring(p);
  587. exit;
  588. end;
  589. setdef : begin
  590. { normalsets are handled separate }
  591. if not(psetdef(p^.left^.resulttype)^.settype=smallset) then
  592. begin
  593. addset(p);
  594. exit;
  595. end;
  596. end;
  597. end;
  598. { defaults }
  599. unsigned:=false;
  600. is_in_dest:=false;
  601. extra_not:=false;
  602. noswap:=false;
  603. opsize:=S_L;
  604. { are we a (small)set, must be set here because the side can be
  605. swapped ! (PFV) }
  606. is_set:=(p^.left^.resulttype^.deftype=setdef);
  607. { calculate the operator which is more difficult }
  608. firstcomplex(p);
  609. { handling boolean expressions extra: }
  610. if is_boolean(p^.left^.resulttype) and
  611. is_boolean(p^.right^.resulttype) then
  612. begin
  613. if (porddef(p^.left^.resulttype)^.typ=bool8bit) or
  614. (porddef(p^.right^.resulttype)^.typ=bool8bit) then
  615. opsize:=S_B
  616. else
  617. if (porddef(p^.left^.resulttype)^.typ=bool16bit) or
  618. (porddef(p^.right^.resulttype)^.typ=bool16bit) then
  619. opsize:=S_W
  620. else
  621. opsize:=S_L;
  622. case p^.treetype of
  623. andn,
  624. orn : begin
  625. clear_location(p^.location);
  626. p^.location.loc:=LOC_JUMP;
  627. cmpop:=false;
  628. case p^.treetype of
  629. andn : begin
  630. otl:=truelabel;
  631. getlabel(truelabel);
  632. secondpass(p^.left);
  633. maketojumpbool(p^.left);
  634. emitlab(truelabel);
  635. truelabel:=otl;
  636. end;
  637. orn : begin
  638. ofl:=falselabel;
  639. getlabel(falselabel);
  640. secondpass(p^.left);
  641. maketojumpbool(p^.left);
  642. emitlab(falselabel);
  643. falselabel:=ofl;
  644. end;
  645. else
  646. CGMessage(type_e_mismatch);
  647. end;
  648. secondpass(p^.right);
  649. maketojumpbool(p^.right);
  650. end;
  651. unequaln,ltn,lten,gtn,gten,
  652. equaln,xorn : begin
  653. if p^.left^.treetype=ordconstn then
  654. swaptree(p);
  655. if p^.left^.location.loc=LOC_JUMP then
  656. begin
  657. otl:=truelabel;
  658. getlabel(truelabel);
  659. ofl:=falselabel;
  660. getlabel(falselabel);
  661. end;
  662. secondpass(p^.left);
  663. { if in flags then copy first to register, because the
  664. flags can be destroyed }
  665. case p^.left^.location.loc of
  666. LOC_FLAGS:
  667. locflags2reg(p^.left^.location,opsize);
  668. LOC_JUMP:
  669. begin
  670. case opsize of
  671. S_L : hregister:=getregister32;
  672. S_W : hregister:=reg32toreg16(getregister32);
  673. S_B : hregister:=reg32toreg8(getregister32);
  674. end;
  675. p^.left^.location.loc:=LOC_REGISTER;
  676. p^.left^.location.register:=hregister;
  677. emitlab(truelabel);
  678. truelabel:=otl;
  679. emit_const_reg(A_MOV,opsize,1,hregister);
  680. getlabel(hl);
  681. emitjmp(C_None,hl);
  682. emitlab(falselabel);
  683. falselabel:=ofl;
  684. emit_reg_reg(A_XOR,S_L,makereg32(hregister),
  685. makereg32(hregister));
  686. emitlab(hl);
  687. end;
  688. end;
  689. set_location(p^.location,p^.left^.location);
  690. pushed:=maybe_push(p^.right^.registers32,p,false);
  691. if p^.right^.location.loc=LOC_JUMP then
  692. begin
  693. otl:=truelabel;
  694. getlabel(truelabel);
  695. ofl:=falselabel;
  696. getlabel(falselabel);
  697. end;
  698. secondpass(p^.right);
  699. if pushed then
  700. begin
  701. restore(p,false);
  702. set_location(p^.left^.location,p^.location);
  703. end;
  704. case p^.right^.location.loc of
  705. LOC_FLAGS:
  706. locflags2reg(p^.right^.location,opsize);
  707. LOC_JUMP:
  708. begin
  709. case opsize of
  710. S_L : hregister:=getregister32;
  711. S_W : hregister:=reg32toreg16(getregister32);
  712. S_B : hregister:=reg32toreg8(getregister32);
  713. end;
  714. p^.right^.location.loc:=LOC_REGISTER;
  715. p^.right^.location.register:=hregister;
  716. emitlab(truelabel);
  717. truelabel:=otl;
  718. emit_const_reg(A_MOV,opsize,1,hregister);
  719. getlabel(hl);
  720. emitjmp(C_None,hl);
  721. emitlab(falselabel);
  722. falselabel:=ofl;
  723. emit_reg_reg(A_XOR,S_L,makereg32(hregister),
  724. makereg32(hregister));
  725. emitlab(hl);
  726. end;
  727. end;
  728. goto do_normal;
  729. end
  730. else
  731. CGMessage(type_e_mismatch);
  732. end
  733. end
  734. else
  735. begin
  736. { in case of constant put it to the left }
  737. if (p^.left^.treetype=ordconstn) then
  738. swaptree(p);
  739. secondpass(p^.left);
  740. { this will be complicated as
  741. a lot of code below assumes that
  742. p^.location and p^.left^.location are the same }
  743. {$ifdef test_dest_loc}
  744. if dest_loc_known and (dest_loc_tree=p) and
  745. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  746. begin
  747. set_location(p^.location,dest_loc);
  748. in_dest_loc:=true;
  749. is_in_dest:=true;
  750. end
  751. else
  752. {$endif test_dest_loc}
  753. set_location(p^.location,p^.left^.location);
  754. { are too few registers free? }
  755. pushed:=maybe_push(p^.right^.registers32,p,is_64bitint(p^.left^.resulttype));
  756. secondpass(p^.right);
  757. if pushed then
  758. begin
  759. restore(p,is_64bitint(p^.left^.resulttype));
  760. set_location(p^.left^.location,p^.location);
  761. end;
  762. if (p^.left^.resulttype^.deftype=pointerdef) or
  763. (p^.right^.resulttype^.deftype=pointerdef) or
  764. ((p^.right^.resulttype^.deftype=objectdef) and
  765. pobjectdef(p^.right^.resulttype)^.is_class and
  766. (p^.left^.resulttype^.deftype=objectdef) and
  767. pobjectdef(p^.left^.resulttype)^.is_class
  768. ) or
  769. (p^.left^.resulttype^.deftype=classrefdef) or
  770. (p^.left^.resulttype^.deftype=procvardef) or
  771. ((p^.left^.resulttype^.deftype=enumdef) and
  772. (p^.left^.resulttype^.size=4)) or
  773. ((p^.left^.resulttype^.deftype=orddef) and
  774. (porddef(p^.left^.resulttype)^.typ=s32bit)) or
  775. ((p^.right^.resulttype^.deftype=orddef) and
  776. (porddef(p^.right^.resulttype)^.typ=s32bit)) or
  777. ((p^.left^.resulttype^.deftype=orddef) and
  778. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  779. ((p^.right^.resulttype^.deftype=orddef) and
  780. (porddef(p^.right^.resulttype)^.typ=u32bit)) or
  781. { as well as small sets }
  782. is_set then
  783. begin
  784. do_normal:
  785. mboverflow:=false;
  786. cmpop:=false;
  787. {$ifndef cardinalmulfix}
  788. unsigned :=
  789. (p^.left^.resulttype^.deftype=pointerdef) or
  790. (p^.right^.resulttype^.deftype=pointerdef) or
  791. ((p^.left^.resulttype^.deftype=orddef) and
  792. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  793. ((p^.right^.resulttype^.deftype=orddef) and
  794. (porddef(p^.right^.resulttype)^.typ=u32bit));
  795. {$else cardinalmulfix}
  796. unsigned := not(is_signed(p^.left^.resulttype)) or
  797. not(is_signed(p^.right^.resulttype));
  798. {$endif cardinalmulfix}
  799. case p^.treetype of
  800. addn : begin
  801. if is_set then
  802. begin
  803. { adding elements is not commutative }
  804. if p^.swaped and (p^.left^.treetype=setelementn) then
  805. swaptree(p);
  806. { are we adding set elements ? }
  807. if p^.right^.treetype=setelementn then
  808. begin
  809. { no range support for smallsets! }
  810. if assigned(p^.right^.right) then
  811. internalerror(43244);
  812. { bts requires both elements to be registers }
  813. if p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  814. begin
  815. ungetiftemp(p^.left^.location.reference);
  816. del_location(p^.left^.location);
  817. {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  818. hregister:=getregister32;
  819. emit_ref_reg(A_MOV,opsize,
  820. newreference(p^.left^.location.reference),hregister);
  821. clear_location(p^.left^.location);
  822. p^.left^.location.loc:=LOC_REGISTER;
  823. p^.left^.location.register:=hregister;
  824. set_location(p^.location,p^.left^.location);
  825. end;
  826. if p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  827. begin
  828. ungetiftemp(p^.right^.location.reference);
  829. del_location(p^.right^.location);
  830. hregister:=getregister32;
  831. emit_ref_reg(A_MOV,opsize,
  832. newreference(p^.right^.location.reference),hregister);
  833. clear_location(p^.right^.location);
  834. p^.right^.location.loc:=LOC_REGISTER;
  835. p^.right^.location.register:=hregister;
  836. end;
  837. op:=A_BTS;
  838. noswap:=true;
  839. end
  840. else
  841. op:=A_OR;
  842. mboverflow:=false;
  843. unsigned:=false;
  844. end
  845. else
  846. begin
  847. op:=A_ADD;
  848. mboverflow:=true;
  849. end;
  850. end;
  851. symdifn : begin
  852. { the symetric diff is only for sets }
  853. if is_set then
  854. begin
  855. op:=A_XOR;
  856. mboverflow:=false;
  857. unsigned:=false;
  858. end
  859. else
  860. CGMessage(type_e_mismatch);
  861. end;
  862. muln : begin
  863. if is_set then
  864. begin
  865. op:=A_AND;
  866. mboverflow:=false;
  867. unsigned:=false;
  868. end
  869. else
  870. begin
  871. if unsigned then
  872. op:=A_MUL
  873. else
  874. op:=A_IMUL;
  875. mboverflow:=true;
  876. end;
  877. end;
  878. subn : begin
  879. if is_set then
  880. begin
  881. op:=A_AND;
  882. mboverflow:=false;
  883. unsigned:=false;
  884. {$IfNDef NoSetConstNot}
  885. If (p^.right^.treetype = setconstn) then
  886. p^.right^.location.reference.offset := not(p^.right^.location.reference.offset)
  887. Else
  888. {$EndIf NoNosetConstNot}
  889. extra_not:=true;
  890. end
  891. else
  892. begin
  893. op:=A_SUB;
  894. mboverflow:=true;
  895. end;
  896. end;
  897. ltn,lten,
  898. gtn,gten,
  899. equaln,unequaln : begin
  900. {$IfNDef NoSetInclusion}
  901. If is_set Then
  902. Case p^.treetype of
  903. lten,gten:
  904. Begin
  905. If p^.treetype = lten then
  906. swaptree(p);
  907. if p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  908. begin
  909. ungetiftemp(p^.left^.location.reference);
  910. del_reference(p^.left^.location.reference);
  911. hregister:=getregister32;
  912. emit_ref_reg(A_MOV,opsize,
  913. newreference(p^.left^.location.reference),hregister);
  914. clear_location(p^.left^.location);
  915. p^.left^.location.loc:=LOC_REGISTER;
  916. p^.left^.location.register:=hregister;
  917. set_location(p^.location,p^.left^.location);
  918. end
  919. else
  920. if p^.left^.location.loc = LOC_CREGISTER Then
  921. {save the register var in a temp register, because
  922. its value is going to be modified}
  923. begin
  924. hregister := getregister32;
  925. emit_reg_reg(A_MOV,opsize,
  926. p^.left^.location.register,hregister);
  927. clear_location(p^.left^.location);
  928. p^.left^.location.loc:=LOC_REGISTER;
  929. p^.left^.location.register:=hregister;
  930. set_location(p^.location,p^.left^.location);
  931. end;
  932. {here, p^.left^.location should be LOC_REGISTER}
  933. If p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE] Then
  934. emit_ref_reg(A_AND,opsize,
  935. newreference(p^.right^.location.reference),p^.left^.location.register)
  936. Else
  937. emit_reg_reg(A_AND,opsize,
  938. p^.right^.location.register,p^.left^.location.register);
  939. {warning: ugly hack ahead: we need a "jne" after the cmp, so
  940. change the treetype from lten/gten to equaln}
  941. p^.treetype := equaln
  942. End;
  943. {no < or > support for sets}
  944. ltn,gtn: CGMessage(type_e_mismatch);
  945. End;
  946. {$EndIf NoSetInclusion}
  947. op:=A_CMP;
  948. cmpop:=true;
  949. end;
  950. xorn : op:=A_XOR;
  951. orn : op:=A_OR;
  952. andn : op:=A_AND;
  953. else
  954. CGMessage(type_e_mismatch);
  955. end;
  956. { filter MUL, which requires special handling }
  957. if op=A_MUL then
  958. begin
  959. popeax:=false;
  960. popedx:=false;
  961. { here you need to free the symbol first }
  962. { p^.left^.location and p^.right^.location must }
  963. { only be freed when they are really released, }
  964. { because the optimizer NEEDS correct regalloc }
  965. { info!!! (JM) }
  966. clear_location(p^.location);
  967. { the p^.location.register will be filled in later (JM) }
  968. p^.location.loc:=LOC_REGISTER;
  969. {$IfNDef NoShlMul}
  970. if p^.right^.treetype=ordconstn then
  971. swaptree(p);
  972. If (p^.left^.treetype = ordconstn) and
  973. ispowerof2(p^.left^.value, power) and
  974. not(cs_check_overflow in aktlocalswitches) then
  975. Begin
  976. { This release will be moved after the next }
  977. { instruction by the optimizer. No need to }
  978. { release p^.left^.location, since it's a }
  979. { constant (JM) }
  980. release_loc(p^.right^.location);
  981. p^.location.register := getregister32;
  982. emitloadord2reg(p^.right^.location,u32bitdef,p^.location.register,true);
  983. emit_const_reg(A_SHL,S_L,power,p^.location.register)
  984. End
  985. Else
  986. Begin
  987. {$EndIf NoShlMul}
  988. regstopush := $ff;
  989. remove_non_regvars_from_loc(p^.right^.location,regstopush);
  990. remove_non_regvars_from_loc(p^.left^.location,regstopush);
  991. { now, regstopush does NOT contain EAX and/or EDX if they are }
  992. { used in either the left or the right location, excepts if }
  993. {they are regvars. It DOES contain them if they are used in }
  994. { another location (JM) }
  995. if not(R_EAX in unused) and ((regstopush and ($80 shr byte(R_EAX))) <> 0) then
  996. begin
  997. emit_reg(A_PUSH,S_L,R_EAX);
  998. popeax:=true;
  999. end;
  1000. if not(R_EDX in unused) and ((regstopush and ($80 shr byte(R_EDX))) <> 0) then
  1001. begin
  1002. emit_reg(A_PUSH,S_L,R_EDX);
  1003. popedx:=true;
  1004. end;
  1005. { p^.left^.location can be R_EAX !!! }
  1006. {$ifndef noAllocEdi}
  1007. getexplicitregister32(R_EDI);
  1008. {$endif noAllocEdi}
  1009. { load the left value }
  1010. emitloadord2reg(p^.left^.location,u32bitdef,R_EDI,true);
  1011. release_loc(p^.left^.location);
  1012. { allocate EAX }
  1013. if R_EAX in unused then
  1014. exprasmlist^.concat(new(pairegalloc,alloc(R_EAX)));
  1015. { load he right value }
  1016. emitloadord2reg(p^.right^.location,u32bitdef,R_EAX,true);
  1017. release_loc(p^.right^.location);
  1018. { allocate EAX if it isn't yet allocated (JM) }
  1019. if (R_EAX in unused) then
  1020. exprasmlist^.concat(new(pairegalloc,alloc(R_EAX)));
  1021. {$ifndef noAllocEdi}
  1022. { also allocate EDX, since it is also modified by }
  1023. { a mul (JM) }
  1024. if R_EDX in unused then
  1025. exprasmlist^.concat(new(pairegalloc,alloc(R_EDX)));
  1026. {$endif noAllocEdi}
  1027. emit_reg(A_MUL,S_L,R_EDI);
  1028. {$ifndef noAllocEdi}
  1029. ungetregister32(R_EDI);
  1030. if R_EDX in unused then
  1031. exprasmlist^.concat(new(pairegalloc,dealloc(R_EDX)));
  1032. {$endif noAllocEdi}
  1033. if R_EAX in unused then
  1034. exprasmlist^.concat(new(pairegalloc,dealloc(R_EAX)));
  1035. p^.location.register := getregister32;
  1036. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.register);
  1037. if popedx then
  1038. emit_reg(A_POP,S_L,R_EDX);
  1039. if popeax then
  1040. emit_reg(A_POP,S_L,R_EAX);
  1041. {$IfNDef NoShlMul}
  1042. End;
  1043. {$endif NoShlMul}
  1044. SetResultLocation(false,true,p);
  1045. exit;
  1046. end;
  1047. { Convert flags to register first }
  1048. if (p^.left^.location.loc=LOC_FLAGS) then
  1049. locflags2reg(p^.left^.location,opsize);
  1050. if (p^.right^.location.loc=LOC_FLAGS) then
  1051. locflags2reg(p^.right^.location,opsize);
  1052. { left and right no register? }
  1053. { then one must be demanded }
  1054. if (p^.left^.location.loc<>LOC_REGISTER) and
  1055. (p^.right^.location.loc<>LOC_REGISTER) then
  1056. begin
  1057. { register variable ? }
  1058. if (p^.left^.location.loc=LOC_CREGISTER) then
  1059. begin
  1060. { it is OK if this is the destination }
  1061. if is_in_dest then
  1062. begin
  1063. hregister:=p^.location.register;
  1064. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  1065. hregister);
  1066. end
  1067. else
  1068. if cmpop then
  1069. begin
  1070. { do not disturb the register }
  1071. hregister:=p^.location.register;
  1072. end
  1073. else
  1074. begin
  1075. case opsize of
  1076. S_L : hregister:=getregister32;
  1077. S_B : hregister:=reg32toreg8(getregister32);
  1078. end;
  1079. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  1080. hregister);
  1081. end
  1082. end
  1083. else
  1084. begin
  1085. ungetiftemp(p^.left^.location.reference);
  1086. del_reference(p^.left^.location.reference);
  1087. if is_in_dest then
  1088. begin
  1089. hregister:=p^.location.register;
  1090. emit_ref_reg(A_MOV,opsize,
  1091. newreference(p^.left^.location.reference),hregister);
  1092. end
  1093. else
  1094. begin
  1095. { first give free, then demand new register }
  1096. case opsize of
  1097. S_L : hregister:=getregister32;
  1098. S_W : hregister:=reg32toreg16(getregister32);
  1099. S_B : hregister:=reg32toreg8(getregister32);
  1100. end;
  1101. emit_ref_reg(A_MOV,opsize,
  1102. newreference(p^.left^.location.reference),hregister);
  1103. end;
  1104. end;
  1105. clear_location(p^.location);
  1106. p^.location.loc:=LOC_REGISTER;
  1107. p^.location.register:=hregister;
  1108. end
  1109. else
  1110. { if on the right the register then swap }
  1111. if not(noswap) and (p^.right^.location.loc=LOC_REGISTER) then
  1112. begin
  1113. swap_location(p^.location,p^.right^.location);
  1114. { newly swapped also set swapped flag }
  1115. p^.swaped:=not(p^.swaped);
  1116. end;
  1117. { at this point, p^.location.loc should be LOC_REGISTER }
  1118. { and p^.location.register should be a valid register }
  1119. { containing the left result }
  1120. if p^.right^.location.loc<>LOC_REGISTER then
  1121. begin
  1122. if (p^.treetype=subn) and p^.swaped then
  1123. begin
  1124. if p^.right^.location.loc=LOC_CREGISTER then
  1125. begin
  1126. if extra_not then
  1127. emit_reg(A_NOT,opsize,p^.location.register);
  1128. {$ifndef noAllocEdi}
  1129. getexplicitregister32(R_EDI);
  1130. {$endif noAllocEdi}
  1131. emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  1132. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  1133. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  1134. {$ifndef noAllocEdi}
  1135. ungetregister32(R_EDI);
  1136. {$endif noAllocEdi}
  1137. end
  1138. else
  1139. begin
  1140. if extra_not then
  1141. emit_reg(A_NOT,opsize,p^.location.register);
  1142. {$ifndef noAllocEdi}
  1143. getexplicitregister32(R_EDI);
  1144. {$endif noAllocEdi}
  1145. emit_ref_reg(A_MOV,opsize,
  1146. newreference(p^.right^.location.reference),R_EDI);
  1147. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  1148. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  1149. {$ifndef noAllocEdi}
  1150. ungetregister32(R_EDI);
  1151. {$endif noAllocEdi}
  1152. ungetiftemp(p^.right^.location.reference);
  1153. del_reference(p^.right^.location.reference);
  1154. end;
  1155. end
  1156. else
  1157. begin
  1158. if (p^.right^.treetype=ordconstn) and
  1159. (op=A_CMP) and
  1160. (p^.right^.value=0) then
  1161. begin
  1162. emit_reg_reg(A_TEST,opsize,p^.location.register,
  1163. p^.location.register);
  1164. end
  1165. else if (p^.right^.treetype=ordconstn) and
  1166. (op=A_ADD) and
  1167. (p^.right^.value=1) and
  1168. not(cs_check_overflow in aktlocalswitches) then
  1169. begin
  1170. emit_reg(A_INC,opsize,
  1171. p^.location.register);
  1172. end
  1173. else if (p^.right^.treetype=ordconstn) and
  1174. (op=A_SUB) and
  1175. (p^.right^.value=1) and
  1176. not(cs_check_overflow in aktlocalswitches) then
  1177. begin
  1178. emit_reg(A_DEC,opsize,
  1179. p^.location.register);
  1180. end
  1181. else if (p^.right^.treetype=ordconstn) and
  1182. (op=A_IMUL) and
  1183. (ispowerof2(p^.right^.value,power)) and
  1184. not(cs_check_overflow in aktlocalswitches) then
  1185. begin
  1186. emit_const_reg(A_SHL,opsize,power,
  1187. p^.location.register);
  1188. end
  1189. else
  1190. begin
  1191. if (p^.right^.location.loc=LOC_CREGISTER) then
  1192. begin
  1193. if extra_not then
  1194. begin
  1195. {$ifndef noAllocEdi}
  1196. getexplicitregister32(R_EDI);
  1197. {$endif noAllocEdi}
  1198. emit_reg_reg(A_MOV,S_L,p^.right^.location.register,R_EDI);
  1199. emit_reg(A_NOT,S_L,R_EDI);
  1200. emit_reg_reg(A_AND,S_L,R_EDI,
  1201. p^.location.register);
  1202. {$ifndef noAllocEdi}
  1203. ungetregister32(R_EDI);
  1204. {$endif noAllocEdi}
  1205. end
  1206. else
  1207. begin
  1208. emit_reg_reg(op,opsize,p^.right^.location.register,
  1209. p^.location.register);
  1210. end;
  1211. end
  1212. else
  1213. begin
  1214. if extra_not then
  1215. begin
  1216. {$ifndef noAllocEdi}
  1217. getexplicitregister32(R_EDI);
  1218. {$endif noAllocEdi}
  1219. emit_ref_reg(A_MOV,S_L,newreference(
  1220. p^.right^.location.reference),R_EDI);
  1221. emit_reg(A_NOT,S_L,R_EDI);
  1222. emit_reg_reg(A_AND,S_L,R_EDI,
  1223. p^.location.register);
  1224. {$ifndef noAllocEdi}
  1225. ungetregister32(R_EDI);
  1226. {$endif noAllocEdi}
  1227. end
  1228. else
  1229. begin
  1230. emit_ref_reg(op,opsize,newreference(
  1231. p^.right^.location.reference),p^.location.register);
  1232. end;
  1233. ungetiftemp(p^.right^.location.reference);
  1234. del_reference(p^.right^.location.reference);
  1235. end;
  1236. end;
  1237. end;
  1238. end
  1239. else
  1240. begin
  1241. { when swapped another result register }
  1242. if (p^.treetype=subn) and p^.swaped then
  1243. begin
  1244. if extra_not then
  1245. emit_reg(A_NOT,S_L,p^.location.register);
  1246. emit_reg_reg(op,opsize,
  1247. p^.location.register,p^.right^.location.register);
  1248. swap_location(p^.location,p^.right^.location);
  1249. { newly swapped also set swapped flag }
  1250. { just to maintain ordering }
  1251. p^.swaped:=not(p^.swaped);
  1252. end
  1253. else
  1254. begin
  1255. if extra_not then
  1256. emit_reg(A_NOT,S_L,p^.right^.location.register);
  1257. emit_reg_reg(op,opsize,
  1258. p^.right^.location.register,
  1259. p^.location.register);
  1260. end;
  1261. case opsize of
  1262. S_L : ungetregister32(p^.right^.location.register);
  1263. S_B : ungetregister32(reg8toreg32(p^.right^.location.register));
  1264. end;
  1265. end;
  1266. if cmpop then
  1267. case opsize of
  1268. S_L : ungetregister32(p^.location.register);
  1269. S_B : ungetregister32(reg8toreg32(p^.location.register));
  1270. end;
  1271. { only in case of overflow operations }
  1272. { produce overflow code }
  1273. { we must put it here directly, because sign of operation }
  1274. { is in unsigned VAR!! }
  1275. if mboverflow then
  1276. begin
  1277. if cs_check_overflow in aktlocalswitches then
  1278. begin
  1279. getlabel(hl4);
  1280. if unsigned then
  1281. emitjmp(C_NB,hl4)
  1282. else
  1283. emitjmp(C_NO,hl4);
  1284. emitcall('FPC_OVERFLOW');
  1285. emitlab(hl4);
  1286. end;
  1287. end;
  1288. end
  1289. else
  1290. { Char type }
  1291. if ((p^.left^.resulttype^.deftype=orddef) and
  1292. (porddef(p^.left^.resulttype)^.typ=uchar)) or
  1293. { enumeration type 16 bit }
  1294. ((p^.left^.resulttype^.deftype=enumdef) and
  1295. (p^.left^.resulttype^.size=1)) then
  1296. begin
  1297. case p^.treetype of
  1298. ltn,lten,gtn,gten,
  1299. equaln,unequaln :
  1300. cmpop:=true;
  1301. else CGMessage(type_e_mismatch);
  1302. end;
  1303. unsigned:=true;
  1304. { left and right no register? }
  1305. { the one must be demanded }
  1306. if (p^.location.loc<>LOC_REGISTER) and
  1307. (p^.right^.location.loc<>LOC_REGISTER) then
  1308. begin
  1309. if p^.location.loc=LOC_CREGISTER then
  1310. begin
  1311. if cmpop then
  1312. { do not disturb register }
  1313. hregister:=p^.location.register
  1314. else
  1315. begin
  1316. hregister:=reg32toreg8(getregister32);
  1317. emit_reg_reg(A_MOV,S_B,p^.location.register,
  1318. hregister);
  1319. end;
  1320. end
  1321. else
  1322. begin
  1323. del_reference(p^.location.reference);
  1324. { first give free then demand new register }
  1325. hregister:=reg32toreg8(getregister32);
  1326. emit_ref_reg(A_MOV,S_B,newreference(p^.location.reference),
  1327. hregister);
  1328. end;
  1329. clear_location(p^.location);
  1330. p^.location.loc:=LOC_REGISTER;
  1331. p^.location.register:=hregister;
  1332. end;
  1333. { now p always a register }
  1334. if (p^.right^.location.loc=LOC_REGISTER) and
  1335. (p^.location.loc<>LOC_REGISTER) then
  1336. begin
  1337. swap_location(p^.location,p^.right^.location);
  1338. { newly swapped also set swapped flag }
  1339. p^.swaped:=not(p^.swaped);
  1340. end;
  1341. if p^.right^.location.loc<>LOC_REGISTER then
  1342. begin
  1343. if p^.right^.location.loc=LOC_CREGISTER then
  1344. begin
  1345. emit_reg_reg(A_CMP,S_B,
  1346. p^.right^.location.register,p^.location.register);
  1347. end
  1348. else
  1349. begin
  1350. emit_ref_reg(A_CMP,S_B,newreference(
  1351. p^.right^.location.reference),p^.location.register);
  1352. del_reference(p^.right^.location.reference);
  1353. end;
  1354. end
  1355. else
  1356. begin
  1357. emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  1358. p^.location.register);
  1359. ungetregister32(reg8toreg32(p^.right^.location.register));
  1360. end;
  1361. ungetregister32(reg8toreg32(p^.location.register));
  1362. end
  1363. else
  1364. { 16 bit enumeration type }
  1365. if ((p^.left^.resulttype^.deftype=enumdef) and
  1366. (p^.left^.resulttype^.size=2)) then
  1367. begin
  1368. case p^.treetype of
  1369. ltn,lten,gtn,gten,
  1370. equaln,unequaln :
  1371. cmpop:=true;
  1372. else CGMessage(type_e_mismatch);
  1373. end;
  1374. unsigned:=true;
  1375. { left and right no register? }
  1376. { the one must be demanded }
  1377. if (p^.location.loc<>LOC_REGISTER) and
  1378. (p^.right^.location.loc<>LOC_REGISTER) then
  1379. begin
  1380. if p^.location.loc=LOC_CREGISTER then
  1381. begin
  1382. if cmpop then
  1383. { do not disturb register }
  1384. hregister:=p^.location.register
  1385. else
  1386. begin
  1387. hregister:=reg32toreg16(getregister32);
  1388. emit_reg_reg(A_MOV,S_W,p^.location.register,
  1389. hregister);
  1390. end;
  1391. end
  1392. else
  1393. begin
  1394. del_reference(p^.location.reference);
  1395. { first give free then demand new register }
  1396. hregister:=reg32toreg16(getregister32);
  1397. emit_ref_reg(A_MOV,S_W,newreference(p^.location.reference),
  1398. hregister);
  1399. end;
  1400. clear_location(p^.location);
  1401. p^.location.loc:=LOC_REGISTER;
  1402. p^.location.register:=hregister;
  1403. end;
  1404. { now p always a register }
  1405. if (p^.right^.location.loc=LOC_REGISTER) and
  1406. (p^.location.loc<>LOC_REGISTER) then
  1407. begin
  1408. swap_location(p^.location,p^.right^.location);
  1409. { newly swapped also set swapped flag }
  1410. p^.swaped:=not(p^.swaped);
  1411. end;
  1412. if p^.right^.location.loc<>LOC_REGISTER then
  1413. begin
  1414. if p^.right^.location.loc=LOC_CREGISTER then
  1415. begin
  1416. emit_reg_reg(A_CMP,S_W,
  1417. p^.right^.location.register,p^.location.register);
  1418. end
  1419. else
  1420. begin
  1421. emit_ref_reg(A_CMP,S_W,newreference(
  1422. p^.right^.location.reference),p^.location.register);
  1423. del_reference(p^.right^.location.reference);
  1424. end;
  1425. end
  1426. else
  1427. begin
  1428. emit_reg_reg(A_CMP,S_W,p^.right^.location.register,
  1429. p^.location.register);
  1430. ungetregister32(reg16toreg32(p^.right^.location.register));
  1431. end;
  1432. ungetregister32(reg16toreg32(p^.location.register));
  1433. end
  1434. else
  1435. { 64 bit types }
  1436. if is_64bitint(p^.left^.resulttype) then
  1437. begin
  1438. mboverflow:=false;
  1439. cmpop:=false;
  1440. unsigned:=((p^.left^.resulttype^.deftype=orddef) and
  1441. (porddef(p^.left^.resulttype)^.typ=u64bit)) or
  1442. ((p^.right^.resulttype^.deftype=orddef) and
  1443. (porddef(p^.right^.resulttype)^.typ=u64bit));
  1444. case p^.treetype of
  1445. addn : begin
  1446. begin
  1447. op:=A_ADD;
  1448. op2:=A_ADC;
  1449. mboverflow:=true;
  1450. end;
  1451. end;
  1452. subn : begin
  1453. op:=A_SUB;
  1454. op2:=A_SBB;
  1455. mboverflow:=true;
  1456. end;
  1457. ltn,lten,
  1458. gtn,gten,
  1459. equaln,unequaln:
  1460. begin
  1461. op:=A_CMP;
  1462. op2:=A_CMP;
  1463. cmpop:=true;
  1464. end;
  1465. xorn:
  1466. begin
  1467. op:=A_XOR;
  1468. op2:=A_XOR;
  1469. end;
  1470. orn:
  1471. begin
  1472. op:=A_OR;
  1473. op2:=A_OR;
  1474. end;
  1475. andn:
  1476. begin
  1477. op:=A_AND;
  1478. op2:=A_AND;
  1479. end;
  1480. muln:
  1481. ;
  1482. else
  1483. CGMessage(type_e_mismatch);
  1484. end;
  1485. if p^.treetype=muln then
  1486. begin
  1487. { save p^.lcoation, because we change it now }
  1488. set_location(hloc,p^.location);
  1489. release_qword_loc(p^.location);
  1490. release_qword_loc(p^.right^.location);
  1491. p^.location.registerlow:=getexplicitregister32(R_EAX);
  1492. p^.location.registerhigh:=getexplicitregister32(R_EDX);
  1493. pushusedregisters(pushedreg,$ff
  1494. and not($80 shr byte(p^.location.registerlow))
  1495. and not($80 shr byte(p^.location.registerhigh)));
  1496. if cs_check_overflow in aktlocalswitches then
  1497. push_int(1)
  1498. else
  1499. push_int(0);
  1500. { the left operand is in hloc, because the
  1501. location of left is p^.location but p^.location
  1502. is already destroyed
  1503. }
  1504. emit_pushq_loc(hloc);
  1505. clear_location(hloc);
  1506. emit_pushq_loc(p^.right^.location);
  1507. if porddef(p^.resulttype)^.typ=u64bit then
  1508. emitcall('FPC_MUL_QWORD')
  1509. else
  1510. emitcall('FPC_MUL_INT64');
  1511. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.registerlow);
  1512. emit_reg_reg(A_MOV,S_L,R_EDX,p^.location.registerhigh);
  1513. popusedregisters(pushedreg);
  1514. p^.location.loc:=LOC_REGISTER;
  1515. end
  1516. else
  1517. begin
  1518. { left and right no register? }
  1519. { then one must be demanded }
  1520. if (p^.left^.location.loc<>LOC_REGISTER) and
  1521. (p^.right^.location.loc<>LOC_REGISTER) then
  1522. begin
  1523. { register variable ? }
  1524. if (p^.left^.location.loc=LOC_CREGISTER) then
  1525. begin
  1526. { it is OK if this is the destination }
  1527. if is_in_dest then
  1528. begin
  1529. hregister:=p^.location.registerlow;
  1530. hregister2:=p^.location.registerhigh;
  1531. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  1532. hregister);
  1533. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  1534. hregister2);
  1535. end
  1536. else
  1537. if cmpop then
  1538. begin
  1539. { do not disturb the register }
  1540. hregister:=p^.location.registerlow;
  1541. hregister2:=p^.location.registerhigh;
  1542. end
  1543. else
  1544. begin
  1545. hregister:=getregister32;
  1546. hregister2:=getregister32;
  1547. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  1548. hregister);
  1549. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerhigh,
  1550. hregister2);
  1551. end
  1552. end
  1553. else
  1554. begin
  1555. ungetiftemp(p^.left^.location.reference);
  1556. del_reference(p^.left^.location.reference);
  1557. if is_in_dest then
  1558. begin
  1559. hregister:=p^.location.registerlow;
  1560. hregister2:=p^.location.registerhigh;
  1561. emit_ref_reg(A_MOV,S_L,
  1562. newreference(p^.left^.location.reference),hregister);
  1563. hr:=newreference(p^.left^.location.reference);
  1564. inc(hr^.offset,4);
  1565. emit_ref_reg(A_MOV,S_L,
  1566. hr,hregister2);
  1567. end
  1568. else
  1569. begin
  1570. hregister:=getregister32;
  1571. hregister2:=getregister32;
  1572. emit_ref_reg(A_MOV,S_L,
  1573. newreference(p^.left^.location.reference),hregister);
  1574. hr:=newreference(p^.left^.location.reference);
  1575. inc(hr^.offset,4);
  1576. emit_ref_reg(A_MOV,S_L,
  1577. hr,hregister2);
  1578. end;
  1579. end;
  1580. clear_location(p^.location);
  1581. p^.location.loc:=LOC_REGISTER;
  1582. p^.location.registerlow:=hregister;
  1583. p^.location.registerhigh:=hregister2;
  1584. end
  1585. else
  1586. { if on the right the register then swap }
  1587. if not(noswap) and (p^.right^.location.loc=LOC_REGISTER) then
  1588. begin
  1589. swap_location(p^.location,p^.right^.location);
  1590. { newly swapped also set swapped flag }
  1591. p^.swaped:=not(p^.swaped);
  1592. end;
  1593. { at this point, p^.location.loc should be LOC_REGISTER }
  1594. { and p^.location.register should be a valid register }
  1595. { containing the left result }
  1596. if p^.right^.location.loc<>LOC_REGISTER then
  1597. begin
  1598. if (p^.treetype=subn) and p^.swaped then
  1599. begin
  1600. if p^.right^.location.loc=LOC_CREGISTER then
  1601. begin
  1602. {$ifndef noAllocEdi}
  1603. getexplicitregister32(R_EDI);
  1604. {$endif noAllocEdi}
  1605. emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  1606. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  1607. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  1608. {$ifndef noAllocEdi}
  1609. ungetregister32(R_EDI);
  1610. getexplicitregister32(R_EDI);
  1611. {$endif noAllocEdi}
  1612. emit_reg_reg(A_MOV,opsize,p^.right^.location.registerhigh,R_EDI);
  1613. { the carry flag is still ok }
  1614. emit_reg_reg(op2,opsize,p^.location.registerhigh,R_EDI);
  1615. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.registerhigh);
  1616. {$ifndef noAllocEdi}
  1617. ungetregister32(R_EDI);
  1618. {$endif noAllocEdi}
  1619. end
  1620. else
  1621. begin
  1622. {$ifndef noAllocEdi}
  1623. getexplicitregister32(R_EDI);
  1624. {$endif noAllocEdi}
  1625. emit_ref_reg(A_MOV,opsize,
  1626. newreference(p^.right^.location.reference),R_EDI);
  1627. emit_reg_reg(op,opsize,p^.location.registerlow,R_EDI);
  1628. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.registerlow);
  1629. {$ifndef noAllocEdi}
  1630. ungetregister32(R_EDI);
  1631. getexplicitregister32(R_EDI);
  1632. {$endif noAllocEdi}
  1633. hr:=newreference(p^.right^.location.reference);
  1634. inc(hr^.offset,4);
  1635. emit_ref_reg(A_MOV,opsize,
  1636. hr,R_EDI);
  1637. { here the carry flag is still preserved }
  1638. emit_reg_reg(op2,opsize,p^.location.registerhigh,R_EDI);
  1639. emit_reg_reg(A_MOV,opsize,R_EDI,
  1640. p^.location.registerhigh);
  1641. {$ifndef noAllocEdi}
  1642. ungetregister32(R_EDI);
  1643. {$endif noAllocEdi}
  1644. ungetiftemp(p^.right^.location.reference);
  1645. del_reference(p^.right^.location.reference);
  1646. end;
  1647. end
  1648. else if cmpop then
  1649. begin
  1650. if (p^.right^.location.loc=LOC_CREGISTER) then
  1651. begin
  1652. emit_reg_reg(A_CMP,S_L,p^.right^.location.registerhigh,
  1653. p^.location.registerhigh);
  1654. firstjmp64bitcmp;
  1655. emit_reg_reg(A_CMP,S_L,p^.right^.location.registerlow,
  1656. p^.location.registerlow);
  1657. secondjmp64bitcmp;
  1658. end
  1659. else
  1660. begin
  1661. hr:=newreference(p^.right^.location.reference);
  1662. inc(hr^.offset,4);
  1663. emit_ref_reg(A_CMP,S_L,
  1664. hr,p^.location.registerhigh);
  1665. firstjmp64bitcmp;
  1666. emit_ref_reg(A_CMP,S_L,newreference(
  1667. p^.right^.location.reference),p^.location.registerlow);
  1668. secondjmp64bitcmp;
  1669. emitjmp(C_None,falselabel);
  1670. ungetiftemp(p^.right^.location.reference);
  1671. del_reference(p^.right^.location.reference);
  1672. end;
  1673. end
  1674. else
  1675. begin
  1676. {
  1677. if (p^.right^.treetype=ordconstn) and
  1678. (op=A_CMP) and
  1679. (p^.right^.value=0) then
  1680. begin
  1681. emit_reg_reg(A_TEST,opsize,p^.location.register,
  1682. p^.location.register);
  1683. end
  1684. else if (p^.right^.treetype=ordconstn) and
  1685. (op=A_IMUL) and
  1686. (ispowerof2(p^.right^.value,power)) then
  1687. begin
  1688. emit_const_reg(A_SHL,opsize,power,
  1689. p^.location.register);
  1690. end
  1691. else
  1692. }
  1693. begin
  1694. if (p^.right^.location.loc=LOC_CREGISTER) then
  1695. begin
  1696. emit_reg_reg(op,S_L,p^.right^.location.registerlow,
  1697. p^.location.registerlow);
  1698. emit_reg_reg(op2,S_L,p^.right^.location.registerhigh,
  1699. p^.location.registerhigh);
  1700. end
  1701. else
  1702. begin
  1703. emit_ref_reg(op,S_L,newreference(
  1704. p^.right^.location.reference),p^.location.registerlow);
  1705. hr:=newreference(p^.right^.location.reference);
  1706. inc(hr^.offset,4);
  1707. emit_ref_reg(op2,S_L,
  1708. hr,p^.location.registerhigh);
  1709. ungetiftemp(p^.right^.location.reference);
  1710. del_reference(p^.right^.location.reference);
  1711. end;
  1712. end;
  1713. end;
  1714. end
  1715. else
  1716. begin
  1717. { when swapped another result register }
  1718. if (p^.treetype=subn) and p^.swaped then
  1719. begin
  1720. emit_reg_reg(op,S_L,
  1721. p^.location.registerlow,
  1722. p^.right^.location.registerlow);
  1723. emit_reg_reg(op2,S_L,
  1724. p^.location.registerhigh,
  1725. p^.right^.location.registerhigh);
  1726. swap_location(p^.location,p^.right^.location);
  1727. { newly swapped also set swapped flag }
  1728. { just to maintain ordering }
  1729. p^.swaped:=not(p^.swaped);
  1730. end
  1731. else if cmpop then
  1732. begin
  1733. emit_reg_reg(A_CMP,S_L,
  1734. p^.right^.location.registerhigh,
  1735. p^.location.registerhigh);
  1736. firstjmp64bitcmp;
  1737. emit_reg_reg(A_CMP,S_L,
  1738. p^.right^.location.registerlow,
  1739. p^.location.registerlow);
  1740. secondjmp64bitcmp;
  1741. end
  1742. else
  1743. begin
  1744. emit_reg_reg(op,S_L,
  1745. p^.right^.location.registerlow,
  1746. p^.location.registerlow);
  1747. emit_reg_reg(op2,S_L,
  1748. p^.right^.location.registerhigh,
  1749. p^.location.registerhigh);
  1750. end;
  1751. ungetregister32(p^.right^.location.registerlow);
  1752. ungetregister32(p^.right^.location.registerhigh);
  1753. end;
  1754. if cmpop then
  1755. begin
  1756. ungetregister32(p^.location.registerlow);
  1757. ungetregister32(p^.location.registerhigh);
  1758. end;
  1759. { only in case of overflow operations }
  1760. { produce overflow code }
  1761. { we must put it here directly, because sign of operation }
  1762. { is in unsigned VAR!! }
  1763. if mboverflow then
  1764. begin
  1765. if cs_check_overflow in aktlocalswitches then
  1766. begin
  1767. getlabel(hl4);
  1768. if unsigned then
  1769. emitjmp(C_NB,hl4)
  1770. else
  1771. emitjmp(C_NO,hl4);
  1772. emitcall('FPC_OVERFLOW');
  1773. emitlab(hl4);
  1774. end;
  1775. end;
  1776. { we have LOC_JUMP as result }
  1777. if cmpop then
  1778. begin
  1779. clear_location(p^.location);
  1780. p^.location.loc:=LOC_JUMP;
  1781. cmpop:=false;
  1782. end;
  1783. end;
  1784. end
  1785. else
  1786. { Floating point }
  1787. if (p^.left^.resulttype^.deftype=floatdef) and
  1788. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  1789. begin
  1790. { real constants to the right, but only if it
  1791. isn't on the FPU stack, i.e. 1.0 or 0.0! }
  1792. if (p^.left^.treetype=realconstn) and
  1793. (p^.left^.location.loc<>LOC_FPU) then
  1794. swaptree(p);
  1795. cmpop:=false;
  1796. case p^.treetype of
  1797. addn : op:=A_FADDP;
  1798. muln : op:=A_FMULP;
  1799. subn : op:=A_FSUBP;
  1800. slashn : op:=A_FDIVP;
  1801. ltn,lten,gtn,gten,
  1802. equaln,unequaln : begin
  1803. op:=A_FCOMPP;
  1804. cmpop:=true;
  1805. end;
  1806. else CGMessage(type_e_mismatch);
  1807. end;
  1808. if (p^.right^.location.loc<>LOC_FPU) then
  1809. begin
  1810. if p^.right^.location.loc=LOC_CFPUREGISTER then
  1811. begin
  1812. emit_reg( A_FLD,S_NO,
  1813. correct_fpuregister(p^.right^.location.register,fpuvaroffset));
  1814. inc(fpuvaroffset);
  1815. end
  1816. else
  1817. floatload(pfloatdef(p^.right^.resulttype)^.typ,p^.right^.location.reference);
  1818. if (p^.left^.location.loc<>LOC_FPU) then
  1819. begin
  1820. if p^.left^.location.loc=LOC_CFPUREGISTER then
  1821. begin
  1822. emit_reg( A_FLD,S_NO,
  1823. correct_fpuregister(p^.left^.location.register,fpuvaroffset));
  1824. inc(fpuvaroffset);
  1825. end
  1826. else
  1827. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  1828. end
  1829. { left was on the stack => swap }
  1830. else
  1831. p^.swaped:=not(p^.swaped);
  1832. { releases the right reference }
  1833. del_reference(p^.right^.location.reference);
  1834. end
  1835. { the nominator in st0 }
  1836. else if (p^.left^.location.loc<>LOC_FPU) then
  1837. begin
  1838. if p^.left^.location.loc=LOC_CFPUREGISTER then
  1839. begin
  1840. emit_reg( A_FLD,S_NO,
  1841. correct_fpuregister(p^.left^.location.register,fpuvaroffset));
  1842. inc(fpuvaroffset);
  1843. end
  1844. else
  1845. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  1846. end
  1847. { fpu operands are always in the wrong order on the stack }
  1848. else
  1849. p^.swaped:=not(p^.swaped);
  1850. { releases the left reference }
  1851. if (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  1852. del_reference(p^.left^.location.reference);
  1853. { if we swaped the tree nodes, then use the reverse operator }
  1854. if p^.swaped then
  1855. begin
  1856. if (p^.treetype=slashn) then
  1857. op:=A_FDIVRP
  1858. else if (p^.treetype=subn) then
  1859. op:=A_FSUBRP;
  1860. end;
  1861. { to avoid the pentium bug
  1862. if (op=FDIVP) and (opt_processors=pentium) then
  1863. emitcall('EMUL_FDIVP')
  1864. else
  1865. }
  1866. { the Intel assemblers want operands }
  1867. if op<>A_FCOMPP then
  1868. begin
  1869. emit_reg_reg(op,S_NO,R_ST,R_ST1);
  1870. dec(fpuvaroffset);
  1871. end
  1872. else
  1873. begin
  1874. emit_none(op,S_NO);
  1875. dec(fpuvaroffset,2);
  1876. end;
  1877. { on comparison load flags }
  1878. if cmpop then
  1879. begin
  1880. if not(R_EAX in unused) then
  1881. begin
  1882. {$ifndef noAllocEdi}
  1883. getexplicitregister32(R_EDI);
  1884. {$endif noAllocEdi}
  1885. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  1886. end;
  1887. emit_reg(A_FNSTSW,S_NO,R_AX);
  1888. emit_none(A_SAHF,S_NO);
  1889. if not(R_EAX in unused) then
  1890. begin
  1891. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  1892. {$ifndef noAllocEdi}
  1893. ungetregister32(R_EDI);
  1894. {$endif noAllocEdi}
  1895. end;
  1896. if p^.swaped then
  1897. begin
  1898. case p^.treetype of
  1899. equaln : flags:=F_E;
  1900. unequaln : flags:=F_NE;
  1901. ltn : flags:=F_A;
  1902. lten : flags:=F_AE;
  1903. gtn : flags:=F_B;
  1904. gten : flags:=F_BE;
  1905. end;
  1906. end
  1907. else
  1908. begin
  1909. case p^.treetype of
  1910. equaln : flags:=F_E;
  1911. unequaln : flags:=F_NE;
  1912. ltn : flags:=F_B;
  1913. lten : flags:=F_BE;
  1914. gtn : flags:=F_A;
  1915. gten : flags:=F_AE;
  1916. end;
  1917. end;
  1918. clear_location(p^.location);
  1919. p^.location.loc:=LOC_FLAGS;
  1920. p^.location.resflags:=flags;
  1921. cmpop:=false;
  1922. end
  1923. else
  1924. begin
  1925. clear_location(p^.location);
  1926. p^.location.loc:=LOC_FPU;
  1927. end;
  1928. end
  1929. {$ifdef SUPPORT_MMX}
  1930. else
  1931. { MMX Arrays }
  1932. if is_mmx_able_array(p^.left^.resulttype) then
  1933. begin
  1934. cmpop:=false;
  1935. mmxbase:=mmx_type(p^.left^.resulttype);
  1936. case p^.treetype of
  1937. addn : begin
  1938. if (cs_mmx_saturation in aktlocalswitches) then
  1939. begin
  1940. case mmxbase of
  1941. mmxs8bit:
  1942. op:=A_PADDSB;
  1943. mmxu8bit:
  1944. op:=A_PADDUSB;
  1945. mmxs16bit,mmxfixed16:
  1946. op:=A_PADDSB;
  1947. mmxu16bit:
  1948. op:=A_PADDUSW;
  1949. end;
  1950. end
  1951. else
  1952. begin
  1953. case mmxbase of
  1954. mmxs8bit,mmxu8bit:
  1955. op:=A_PADDB;
  1956. mmxs16bit,mmxu16bit,mmxfixed16:
  1957. op:=A_PADDW;
  1958. mmxs32bit,mmxu32bit:
  1959. op:=A_PADDD;
  1960. end;
  1961. end;
  1962. end;
  1963. muln : begin
  1964. case mmxbase of
  1965. mmxs16bit,mmxu16bit:
  1966. op:=A_PMULLW;
  1967. mmxfixed16:
  1968. op:=A_PMULHW;
  1969. end;
  1970. end;
  1971. subn : begin
  1972. if (cs_mmx_saturation in aktlocalswitches) then
  1973. begin
  1974. case mmxbase of
  1975. mmxs8bit:
  1976. op:=A_PSUBSB;
  1977. mmxu8bit:
  1978. op:=A_PSUBUSB;
  1979. mmxs16bit,mmxfixed16:
  1980. op:=A_PSUBSB;
  1981. mmxu16bit:
  1982. op:=A_PSUBUSW;
  1983. end;
  1984. end
  1985. else
  1986. begin
  1987. case mmxbase of
  1988. mmxs8bit,mmxu8bit:
  1989. op:=A_PSUBB;
  1990. mmxs16bit,mmxu16bit,mmxfixed16:
  1991. op:=A_PSUBW;
  1992. mmxs32bit,mmxu32bit:
  1993. op:=A_PSUBD;
  1994. end;
  1995. end;
  1996. end;
  1997. {
  1998. ltn,lten,gtn,gten,
  1999. equaln,unequaln :
  2000. begin
  2001. op:=A_CMP;
  2002. cmpop:=true;
  2003. end;
  2004. }
  2005. xorn:
  2006. op:=A_PXOR;
  2007. orn:
  2008. op:=A_POR;
  2009. andn:
  2010. op:=A_PAND;
  2011. else CGMessage(type_e_mismatch);
  2012. end;
  2013. { left and right no register? }
  2014. { then one must be demanded }
  2015. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  2016. (p^.right^.location.loc<>LOC_MMXREGISTER) then
  2017. begin
  2018. { register variable ? }
  2019. if (p^.left^.location.loc=LOC_CMMXREGISTER) then
  2020. begin
  2021. { it is OK if this is the destination }
  2022. if is_in_dest then
  2023. begin
  2024. hregister:=p^.location.register;
  2025. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  2026. hregister);
  2027. end
  2028. else
  2029. begin
  2030. hregister:=getregistermmx;
  2031. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  2032. hregister);
  2033. end
  2034. end
  2035. else
  2036. begin
  2037. del_reference(p^.left^.location.reference);
  2038. if is_in_dest then
  2039. begin
  2040. hregister:=p^.location.register;
  2041. emit_ref_reg(A_MOVQ,S_NO,
  2042. newreference(p^.left^.location.reference),hregister);
  2043. end
  2044. else
  2045. begin
  2046. hregister:=getregistermmx;
  2047. emit_ref_reg(A_MOVQ,S_NO,
  2048. newreference(p^.left^.location.reference),hregister);
  2049. end;
  2050. end;
  2051. clear_location(p^.location);
  2052. p^.location.loc:=LOC_MMXREGISTER;
  2053. p^.location.register:=hregister;
  2054. end
  2055. else
  2056. { if on the right the register then swap }
  2057. if (p^.right^.location.loc=LOC_MMXREGISTER) then
  2058. begin
  2059. swap_location(p^.location,p^.right^.location);
  2060. { newly swapped also set swapped flag }
  2061. p^.swaped:=not(p^.swaped);
  2062. end;
  2063. { at this point, p^.location.loc should be LOC_MMXREGISTER }
  2064. { and p^.location.register should be a valid register }
  2065. { containing the left result }
  2066. if p^.right^.location.loc<>LOC_MMXREGISTER then
  2067. begin
  2068. if (p^.treetype=subn) and p^.swaped then
  2069. begin
  2070. if p^.right^.location.loc=LOC_CMMXREGISTER then
  2071. begin
  2072. emit_reg_reg(A_MOVQ,S_NO,p^.right^.location.register,R_MM7);
  2073. emit_reg_reg(op,S_NO,p^.location.register,R_MM0);
  2074. emit_reg_reg(A_MOVQ,S_NO,R_MM7,p^.location.register);
  2075. end
  2076. else
  2077. begin
  2078. emit_ref_reg(A_MOVQ,S_NO,
  2079. newreference(p^.right^.location.reference),R_MM7);
  2080. emit_reg_reg(op,S_NO,p^.location.register,
  2081. R_MM7);
  2082. emit_reg_reg(A_MOVQ,S_NO,
  2083. R_MM7,p^.location.register);
  2084. del_reference(p^.right^.location.reference);
  2085. end;
  2086. end
  2087. else
  2088. begin
  2089. if (p^.right^.location.loc=LOC_CREGISTER) then
  2090. begin
  2091. emit_reg_reg(op,S_NO,p^.right^.location.register,
  2092. p^.location.register);
  2093. end
  2094. else
  2095. begin
  2096. emit_ref_reg(op,S_NO,newreference(
  2097. p^.right^.location.reference),p^.location.register);
  2098. del_reference(p^.right^.location.reference);
  2099. end;
  2100. end;
  2101. end
  2102. else
  2103. begin
  2104. { when swapped another result register }
  2105. if (p^.treetype=subn) and p^.swaped then
  2106. begin
  2107. emit_reg_reg(op,S_NO,
  2108. p^.location.register,p^.right^.location.register);
  2109. swap_location(p^.location,p^.right^.location);
  2110. { newly swapped also set swapped flag }
  2111. { just to maintain ordering }
  2112. p^.swaped:=not(p^.swaped);
  2113. end
  2114. else
  2115. begin
  2116. emit_reg_reg(op,S_NO,
  2117. p^.right^.location.register,
  2118. p^.location.register);
  2119. end;
  2120. ungetregistermmx(p^.right^.location.register);
  2121. end;
  2122. end
  2123. {$endif SUPPORT_MMX}
  2124. else CGMessage(type_e_mismatch);
  2125. end;
  2126. SetResultLocation(cmpop,unsigned,p);
  2127. end;
  2128. end.
  2129. {
  2130. $Log$
  2131. Revision 1.92 2000-01-23 13:57:52 jonas
  2132. * fixed bug introduced by my regalloc fixed :(
  2133. Revision 1.91 2000/01/23 11:11:36 michael
  2134. + Fixes from Jonas.
  2135. Revision 1.90 2000/01/22 16:02:38 jonas
  2136. * fixed more regalloc bugs (for set adding and unsigned
  2137. multiplication)
  2138. Revision 1.89 2000/01/13 16:52:47 jonas
  2139. * moved deallocation of registers used in reference that points to string after
  2140. copyshortstring (this routine doesn't require extra regs)
  2141. Revision 1.88 2000/01/09 19:44:53 florian
  2142. * bug in secondadd(subn) with swaped mmx operands fixed
  2143. Revision 1.87 2000/01/09 16:35:39 jonas
  2144. + comment about badly placed release_loc calls for a_mul which
  2145. causes wrong regdeallocations. Don't know how to fix :(
  2146. Revision 1.86 2000/01/09 12:34:59 jonas
  2147. * changed edi allocation to use getexplicitregister32/ungetregister
  2148. (adapted tgeni386 a bit for this) and enabled it by default
  2149. * fixed very big and stupid bug of mine in cg386mat that broke the
  2150. include() code (and make cycle :( ) if you compiled without
  2151. -dnewoptimizations
  2152. Revision 1.85 2000/01/09 01:44:18 jonas
  2153. + (de)allocation info for EDI to fix reported bug on mailinglist.
  2154. Also some (de)allocation info for ESI added. Between -dallocEDI
  2155. because at this time of the night bugs could easily slip in ;)
  2156. Revision 1.84 2000/01/07 01:14:20 peter
  2157. * updated copyright to 2000
  2158. Revision 1.83 1999/12/11 18:53:31 jonas
  2159. * fixed type conversions of results of operations with cardinals
  2160. (between -dcardinalmulfix)
  2161. Revision 1.82 1999/11/06 14:34:17 peter
  2162. * truncated log to 20 revs
  2163. Revision 1.81 1999/09/28 19:43:45 florian
  2164. * the maybe_push fix of Pierre wasn't 100%, the tree parameter
  2165. must contain a valid location (which is saved if necessary)
  2166. Revision 1.80 1999/09/26 13:26:01 florian
  2167. * exception patch of Romio nevertheless the excpetion handling
  2168. needs some corections regarding register saving
  2169. * gettempansistring is again a procedure
  2170. Revision 1.79 1999/09/21 20:53:21 florian
  2171. * fixed 1/s problem from mailing list
  2172. Revision 1.78 1999/09/07 07:52:19 peter
  2173. * > < >= <= support for boolean
  2174. * boolean constants are now calculated like integer constants
  2175. Revision 1.77 1999/08/30 12:00:45 pierre
  2176. * problem with maybe_push/restore solved hopefully
  2177. Revision 1.76 1999/08/23 23:31:00 pierre
  2178. * double del_location removed in add_set
  2179. Revision 1.75 1999/08/23 10:35:13 jonas
  2180. * fixed <= and >= for sets
  2181. Revision 1.74 1999/08/19 13:08:43 pierre
  2182. * emit_??? used
  2183. Revision 1.73 1999/08/07 11:29:26 peter
  2184. * better fix for muln register allocation
  2185. Revision 1.72 1999/08/04 13:45:17 florian
  2186. + floating point register variables !!
  2187. * pairegalloc is now generated for register variables
  2188. Revision 1.71 1999/08/04 00:22:40 florian
  2189. * renamed i386asm and i386base to cpuasm and cpubase
  2190. Revision 1.70 1999/08/03 22:02:31 peter
  2191. * moved bitmask constants to sets
  2192. * some other type/const renamings
  2193. Revision 1.69 1999/07/05 20:13:06 peter
  2194. * removed temp defines
  2195. Revision 1.68 1999/07/02 12:18:46 jonas
  2196. * released setconstnot (changed to $ifndef nosetconstnot)
  2197. * released shlmul (changed to $ifndef no shlmul)
  2198. Revision 1.67 1999/06/14 17:47:45 peter
  2199. * merged
  2200. Revision 1.66.2.1 1999/06/14 17:24:40 peter
  2201. * fixed saving of registers with decr_ansistr
  2202. Revision 1.66 1999/06/09 23:22:37 peter
  2203. + del_location
  2204. Revision 1.65 1999/06/09 23:00:11 peter
  2205. * small ansistring fixes
  2206. * val_ansistr_sint destsize changed to longint
  2207. * don't write low/hi ascii with -al
  2208. Revision 1.64 1999/06/02 10:11:39 florian
  2209. * make cycle fixed i.e. compilation with 0.99.10
  2210. * some fixes for qword
  2211. * start of register calling conventions
  2212. Revision 1.63 1999/05/31 20:35:45 peter
  2213. * ansistring fixes, decr_ansistr called after all temp ansi reuses
  2214. }