cg386add.pas 109 KB

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