n386add.pas 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. Code generation for add nodes on the i386
  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 n386add;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nadd,cpubase,cginfo;
  23. type
  24. ti386addnode = class(taddnode)
  25. procedure pass_2;override;
  26. protected
  27. function first_addstring : tnode; override;
  28. private
  29. procedure pass_left_and_right(var pushedfpu:boolean);
  30. function getresflags(unsigned : boolean) : tresflags;
  31. procedure left_must_be_reg(opsize:TOpSize;noswap:boolean);
  32. procedure emit_op_right_left(op:TAsmOp;opsize:TOpSize);
  33. procedure emit_generic_code(op:TAsmOp;opsize:TOpSize;unsigned,extra_not,mboverflow:boolean);
  34. procedure set_result_location(cmpop,unsigned:boolean);
  35. procedure second_addstring;
  36. procedure second_addboolean;
  37. procedure second_addfloat;
  38. procedure second_addsmallset;
  39. {$ifdef SUPPORT_MMX}
  40. procedure second_addmmx;
  41. {$endif SUPPORT_MMX}
  42. procedure second_add64bit;
  43. end;
  44. implementation
  45. uses
  46. globtype,systems,
  47. cutils,verbose,globals,
  48. symconst,symdef,paramgr,
  49. aasmbase,aasmtai,aasmcpu,defutil,htypechk,
  50. cgbase,pass_2,regvars,
  51. cpupara,
  52. ncon,nset,
  53. cga,ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
  54. {*****************************************************************************
  55. Helpers
  56. *****************************************************************************}
  57. const
  58. opsize_2_cgsize : array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32);
  59. procedure ti386addnode.pass_left_and_right(var pushedfpu:boolean);
  60. var
  61. pushedregs : tmaybesave;
  62. begin
  63. { calculate the operator which is more difficult }
  64. firstcomplex(self);
  65. { in case of constant put it to the left }
  66. if (left.nodetype=ordconstn) then
  67. swapleftright;
  68. secondpass(left);
  69. { are too few registers free? }
  70. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  71. if location.loc=LOC_FPUREGISTER then
  72. pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
  73. else
  74. pushedfpu:=false;
  75. secondpass(right);
  76. maybe_restore(exprasmlist,left.location,pushedregs);
  77. end;
  78. function ti386addnode.getresflags(unsigned : boolean) : tresflags;
  79. begin
  80. case nodetype of
  81. equaln : getresflags:=F_E;
  82. unequaln : getresflags:=F_NE;
  83. else
  84. if not(unsigned) then
  85. begin
  86. if nf_swaped in flags then
  87. case nodetype of
  88. ltn : getresflags:=F_G;
  89. lten : getresflags:=F_GE;
  90. gtn : getresflags:=F_L;
  91. gten : getresflags:=F_LE;
  92. end
  93. else
  94. case nodetype of
  95. ltn : getresflags:=F_L;
  96. lten : getresflags:=F_LE;
  97. gtn : getresflags:=F_G;
  98. gten : getresflags:=F_GE;
  99. end;
  100. end
  101. else
  102. begin
  103. if nf_swaped in flags then
  104. case nodetype of
  105. ltn : getresflags:=F_A;
  106. lten : getresflags:=F_AE;
  107. gtn : getresflags:=F_B;
  108. gten : getresflags:=F_BE;
  109. end
  110. else
  111. case nodetype of
  112. ltn : getresflags:=F_B;
  113. lten : getresflags:=F_BE;
  114. gtn : getresflags:=F_A;
  115. gten : getresflags:=F_AE;
  116. end;
  117. end;
  118. end;
  119. end;
  120. procedure ti386addnode.left_must_be_reg(opsize:TOpSize;noswap:boolean);
  121. begin
  122. { left location is not a register? }
  123. if (left.location.loc<>LOC_REGISTER) then
  124. begin
  125. { if right is register then we can swap the locations }
  126. if (not noswap) and
  127. (right.location.loc=LOC_REGISTER) then
  128. begin
  129. location_swap(left.location,right.location);
  130. toggleflag(nf_swaped);
  131. end
  132. else
  133. begin
  134. { maybe we can reuse a constant register when the
  135. operation is a comparison that doesn't change the
  136. value of the register }
  137. location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
  138. end;
  139. end;
  140. end;
  141. procedure ti386addnode.emit_op_right_left(op:TAsmOp;opsize:TOpsize);
  142. begin
  143. { left must be a register }
  144. case right.location.loc of
  145. LOC_REGISTER,
  146. LOC_CREGISTER :
  147. exprasmlist.concat(taicpu.op_reg_reg(op,opsize,right.location.register,left.location.register));
  148. LOC_REFERENCE,
  149. LOC_CREFERENCE :
  150. exprasmlist.concat(taicpu.op_ref_reg(op,opsize,right.location.reference,left.location.register));
  151. LOC_CONSTANT :
  152. exprasmlist.concat(taicpu.op_const_reg(op,opsize,right.location.value,left.location.register));
  153. else
  154. internalerror(200203232);
  155. end;
  156. end;
  157. procedure ti386addnode.set_result_location(cmpop,unsigned:boolean);
  158. begin
  159. if cmpop then
  160. begin
  161. location_reset(location,LOC_FLAGS,OS_NO);
  162. location.resflags:=getresflags(unsigned);
  163. end
  164. else
  165. location_copy(location,left.location);
  166. end;
  167. procedure ti386addnode.emit_generic_code(op:TAsmOp;opsize:TOpSize;unsigned,extra_not,mboverflow:boolean);
  168. var
  169. power : longint;
  170. hl4 : tasmlabel;
  171. r:Tregister;
  172. begin
  173. { at this point, left.location.loc should be LOC_REGISTER }
  174. if right.location.loc=LOC_REGISTER then
  175. begin
  176. { right.location is a LOC_REGISTER }
  177. { when swapped another result register }
  178. if (nodetype=subn) and (nf_swaped in flags) then
  179. begin
  180. if extra_not then
  181. emit_reg(A_NOT,S_L,left.location.register);
  182. emit_reg_reg(op,opsize,left.location.register,right.location.register);
  183. { newly swapped also set swapped flag }
  184. location_swap(left.location,right.location);
  185. toggleflag(nf_swaped);
  186. end
  187. else
  188. begin
  189. if extra_not then
  190. emit_reg(A_NOT,S_L,right.location.register);
  191. emit_reg_reg(op,opsize,right.location.register,left.location.register);
  192. end;
  193. end
  194. else
  195. begin
  196. { right.location is not a LOC_REGISTER }
  197. if (nodetype=subn) and (nf_swaped in flags) then
  198. begin
  199. if extra_not then
  200. emit_reg(A_NOT,opsize,left.location.register);
  201. r.enum:=R_EDI;
  202. rg.getexplicitregisterint(exprasmlist,R_EDI);
  203. cg.a_load_loc_reg(exprasmlist,right.location,r);
  204. emit_reg_reg(op,opsize,left.location.register,r);
  205. emit_reg_reg(A_MOV,opsize,r,left.location.register);
  206. rg.ungetregisterint(exprasmlist,r);
  207. end
  208. else
  209. begin
  210. { Optimizations when right.location is a constant value }
  211. if (op=A_CMP) and
  212. (nodetype in [equaln,unequaln]) and
  213. (right.location.loc=LOC_CONSTANT) and
  214. (right.location.value=0) then
  215. begin
  216. emit_reg_reg(A_TEST,opsize,left.location.register,left.location.register);
  217. end
  218. else
  219. if (op=A_ADD) and
  220. (right.location.loc=LOC_CONSTANT) and
  221. (right.location.value=1) and
  222. not(cs_check_overflow in aktlocalswitches) then
  223. begin
  224. emit_reg(A_INC,opsize,left.location.register);
  225. end
  226. else
  227. if (op=A_SUB) and
  228. (right.location.loc=LOC_CONSTANT) and
  229. (right.location.value=1) and
  230. not(cs_check_overflow in aktlocalswitches) then
  231. begin
  232. emit_reg(A_DEC,opsize,left.location.register);
  233. end
  234. else
  235. if (op=A_IMUL) and
  236. (right.location.loc=LOC_CONSTANT) and
  237. (ispowerof2(right.location.value,power)) and
  238. not(cs_check_overflow in aktlocalswitches) then
  239. begin
  240. emit_const_reg(A_SHL,opsize,power,left.location.register);
  241. end
  242. else
  243. begin
  244. if extra_not then
  245. begin
  246. r.enum:=R_EDI;
  247. rg.getexplicitregisterint(exprasmlist,R_EDI);
  248. cg.a_load_loc_reg(exprasmlist,right.location,r);
  249. emit_reg(A_NOT,S_L,r);
  250. emit_reg_reg(A_AND,S_L,r,left.location.register);
  251. rg.ungetregisterint(exprasmlist,r);
  252. end
  253. else
  254. begin
  255. emit_op_right_left(op,opsize);
  256. end;
  257. end;
  258. end;
  259. end;
  260. { only in case of overflow operations }
  261. { produce overflow code }
  262. { we must put it here directly, because sign of operation }
  263. { is in unsigned VAR!! }
  264. if mboverflow then
  265. begin
  266. if cs_check_overflow in aktlocalswitches then
  267. begin
  268. objectlibrary.getlabel(hl4);
  269. if unsigned then
  270. emitjmp(C_NB,hl4)
  271. else
  272. emitjmp(C_NO,hl4);
  273. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  274. cg.a_label(exprasmlist,hl4);
  275. end;
  276. end;
  277. end;
  278. {*****************************************************************************
  279. Addstring
  280. *****************************************************************************}
  281. { note: if you implemented an fpc_shortstr_concat similar to the }
  282. { one in i386.inc, you have to override first_addstring like in }
  283. { ti386addnode.first_string and implement the shortstring concat }
  284. { manually! The generic routine is different from the i386 one (JM) }
  285. function ti386addnode.first_addstring : tnode;
  286. begin
  287. { special cases for shortstrings, handled in pass_2 (JM) }
  288. { can't handle fpc_shortstr_compare with compilerproc either because it }
  289. { returns its results in the flags instead of in eax }
  290. if (((nodetype = addn) and
  291. is_shortstring(resulttype.def)) or
  292. ((nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) and
  293. not(((left.nodetype=stringconstn) and (str_length(left)=0)) or
  294. ((right.nodetype=stringconstn) and (str_length(right)=0))) and
  295. is_shortstring(left.resulttype.def))) then
  296. begin
  297. if nodetype = addn then
  298. location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def))
  299. else
  300. location_reset(location,LOC_FLAGS,OS_NO);
  301. calcregisters(self,0,0,0);
  302. result := nil;
  303. exit;
  304. end;
  305. { otherwise, use the generic code }
  306. result := inherited first_addstring;
  307. end;
  308. procedure ti386addnode.second_addstring;
  309. var
  310. href : treference;
  311. cmpop : boolean;
  312. pushed : tpushedsaved;
  313. regstopush : tregisterset;
  314. begin
  315. { string operations are not commutative }
  316. if nf_swaped in flags then
  317. swapleftright;
  318. case tstringdef(left.resulttype.def).string_typ of
  319. st_shortstring:
  320. begin
  321. case nodetype of
  322. addn:
  323. begin
  324. cmpop:=false;
  325. secondpass(left);
  326. { if str_concat is set in expr
  327. s:=s+ ... no need to create a temp string (PM) }
  328. { the tempstring can also come from a typeconversion }
  329. { or a function result, so simply check for a }
  330. { temp of 256 bytes(JM) }
  331. if not(tg.istemp(left.location.reference) and
  332. (tg.SizeOfTemp(exprasmlist,left.location.reference) = 256)) and
  333. not(nf_use_strconcat in flags) then
  334. begin
  335. tg.GetTemp(exprasmlist,256,tt_normal,href);
  336. cg.g_copyshortstring(exprasmlist,left.location.reference,href,255,true,false);
  337. { location is released by copyshortstring }
  338. location_freetemp(exprasmlist,left.location);
  339. location_reset(left.location,LOC_CREFERENCE,def_cgsize(resulttype.def));
  340. left.location.reference:=href;
  341. end;
  342. secondpass(right);
  343. { on the right we do not need the register anymore too }
  344. { Instead of releasing them already, simply do not }
  345. { push them (so the release is in the right place, }
  346. { because emitpushreferenceaddr doesn't need extra }
  347. { registers) (JM) }
  348. regstopush := all_registers;
  349. remove_non_regvars_from_loc(right.location,regstopush);
  350. rg.saveusedregisters(exprasmlist,pushed,regstopush);
  351. { push the maximum possible length of the result }
  352. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(2));
  353. { the optimizer can more easily put the }
  354. { deallocations in the right place if it happens }
  355. { too early than when it happens too late (if }
  356. { the pushref needs a "lea (..),edi; push edi") }
  357. location_release(exprasmlist,right.location);
  358. cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(1));
  359. rg.saveregvars(exprasmlist,regstopush);
  360. cg.a_call_name(exprasmlist,'FPC_SHORTSTR_CONCAT');
  361. tg.ungetiftemp(exprasmlist,right.location.reference);
  362. cg.g_maybe_loadself(exprasmlist);
  363. rg.restoreusedregisters(exprasmlist,pushed);
  364. location_copy(location,left.location);
  365. end;
  366. ltn,lten,gtn,gten,equaln,unequaln :
  367. begin
  368. cmpop := true;
  369. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  370. secondpass(left);
  371. location_release(exprasmlist,left.location);
  372. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(2));
  373. secondpass(right);
  374. location_release(exprasmlist,right.location);
  375. cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(1));
  376. rg.saveregvars(exprasmlist,all_registers);
  377. cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
  378. cg.g_maybe_loadself(exprasmlist);
  379. rg.restoreusedregisters(exprasmlist,pushed);
  380. location_freetemp(exprasmlist,left.location);
  381. location_freetemp(exprasmlist,right.location);
  382. end;
  383. end;
  384. set_result_location(cmpop,true);
  385. end;
  386. else
  387. { rest should be handled in first pass (JM) }
  388. internalerror(200108303);
  389. end;
  390. end;
  391. {*****************************************************************************
  392. AddBoolean
  393. *****************************************************************************}
  394. procedure ti386addnode.second_addboolean;
  395. var
  396. op : TAsmOp;
  397. opsize : TOpsize;
  398. cmpop,
  399. isjump : boolean;
  400. otl,ofl : tasmlabel;
  401. pushedregs : tmaybesave;
  402. begin
  403. { calculate the operator which is more difficult }
  404. firstcomplex(self);
  405. cmpop:=false;
  406. if (torddef(left.resulttype.def).typ=bool8bit) or
  407. (torddef(right.resulttype.def).typ=bool8bit) then
  408. opsize:=S_B
  409. else
  410. if (torddef(left.resulttype.def).typ=bool16bit) or
  411. (torddef(right.resulttype.def).typ=bool16bit) then
  412. opsize:=S_W
  413. else
  414. opsize:=S_L;
  415. if (cs_full_boolean_eval in aktlocalswitches) or
  416. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  417. begin
  418. if left.nodetype in [ordconstn,realconstn] then
  419. swapleftright;
  420. isjump:=(left.location.loc=LOC_JUMP);
  421. if isjump then
  422. begin
  423. otl:=truelabel;
  424. objectlibrary.getlabel(truelabel);
  425. ofl:=falselabel;
  426. objectlibrary.getlabel(falselabel);
  427. end;
  428. secondpass(left);
  429. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  430. location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],false);
  431. if isjump then
  432. begin
  433. truelabel:=otl;
  434. falselabel:=ofl;
  435. end;
  436. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  437. isjump:=(right.location.loc=LOC_JUMP);
  438. if isjump then
  439. begin
  440. otl:=truelabel;
  441. objectlibrary.getlabel(truelabel);
  442. ofl:=falselabel;
  443. objectlibrary.getlabel(falselabel);
  444. end;
  445. secondpass(right);
  446. maybe_restore(exprasmlist,left.location,pushedregs);
  447. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  448. location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
  449. if isjump then
  450. begin
  451. truelabel:=otl;
  452. falselabel:=ofl;
  453. end;
  454. { left must be a register }
  455. left_must_be_reg(opsize,false);
  456. { compare the }
  457. case nodetype of
  458. ltn,lten,gtn,gten,
  459. equaln,unequaln :
  460. begin
  461. op:=A_CMP;
  462. cmpop:=true;
  463. end;
  464. xorn :
  465. op:=A_XOR;
  466. orn :
  467. op:=A_OR;
  468. andn :
  469. op:=A_AND;
  470. else
  471. internalerror(200203247);
  472. end;
  473. emit_op_right_left(op,opsize);
  474. location_freetemp(exprasmlist,right.location);
  475. location_release(exprasmlist,right.location);
  476. if cmpop then
  477. begin
  478. location_freetemp(exprasmlist,left.location);
  479. location_release(exprasmlist,left.location);
  480. end;
  481. set_result_location(cmpop,true);
  482. end
  483. else
  484. begin
  485. case nodetype of
  486. andn,
  487. orn :
  488. begin
  489. location_reset(location,LOC_JUMP,OS_NO);
  490. case nodetype of
  491. andn :
  492. begin
  493. otl:=truelabel;
  494. objectlibrary.getlabel(truelabel);
  495. secondpass(left);
  496. maketojumpbool(exprasmlist,left,lr_load_regvars);
  497. cg.a_label(exprasmlist,truelabel);
  498. truelabel:=otl;
  499. end;
  500. orn :
  501. begin
  502. ofl:=falselabel;
  503. objectlibrary.getlabel(falselabel);
  504. secondpass(left);
  505. maketojumpbool(exprasmlist,left,lr_load_regvars);
  506. cg.a_label(exprasmlist,falselabel);
  507. falselabel:=ofl;
  508. end;
  509. else
  510. CGMessage(type_e_mismatch);
  511. end;
  512. secondpass(right);
  513. maketojumpbool(exprasmlist,right,lr_load_regvars);
  514. end;
  515. else
  516. CGMessage(type_e_mismatch);
  517. end;
  518. end;
  519. end;
  520. {*****************************************************************************
  521. AddFloat
  522. *****************************************************************************}
  523. procedure ti386addnode.second_addfloat;
  524. var
  525. op : TAsmOp;
  526. resflags : tresflags;
  527. pushedfpu,
  528. cmpop : boolean;
  529. r,r2:Tregister;
  530. begin
  531. pass_left_and_right(pushedfpu);
  532. cmpop:=false;
  533. case nodetype of
  534. addn :
  535. op:=A_FADDP;
  536. muln :
  537. op:=A_FMULP;
  538. subn :
  539. op:=A_FSUBP;
  540. slashn :
  541. op:=A_FDIVP;
  542. ltn,lten,gtn,gten,
  543. equaln,unequaln :
  544. begin
  545. op:=A_FCOMPP;
  546. cmpop:=true;
  547. end;
  548. else
  549. CGMessage(type_e_mismatch);
  550. end;
  551. if (right.location.loc<>LOC_FPUREGISTER) then
  552. begin
  553. r.enum:=R_ST;
  554. cg.a_loadfpu_loc_reg(exprasmlist,right.location,r);
  555. if (right.location.loc <> LOC_CFPUREGISTER) and
  556. pushedfpu then
  557. location_freetemp(exprasmlist,left.location);
  558. if (left.location.loc<>LOC_FPUREGISTER) then
  559. begin
  560. cg.a_loadfpu_loc_reg(exprasmlist,left.location,r);
  561. if (left.location.loc <> LOC_CFPUREGISTER) and
  562. pushedfpu then
  563. location_freetemp(exprasmlist,left.location);
  564. end
  565. else
  566. begin
  567. { left was on the stack => swap }
  568. toggleflag(nf_swaped);
  569. end;
  570. { releases the right reference }
  571. location_release(exprasmlist,right.location);
  572. end
  573. { the nominator in st0 }
  574. else if (left.location.loc<>LOC_FPUREGISTER) then
  575. begin
  576. r.enum:=R_ST;
  577. cg.a_loadfpu_loc_reg(exprasmlist,left.location,r);
  578. if (left.location.loc <> LOC_CFPUREGISTER) and
  579. pushedfpu then
  580. location_freetemp(exprasmlist,left.location);
  581. end
  582. else
  583. begin
  584. { fpu operands are always in the wrong order on the stack }
  585. toggleflag(nf_swaped);
  586. end;
  587. { releases the left reference }
  588. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  589. location_release(exprasmlist,left.location);
  590. { if we swaped the tree nodes, then use the reverse operator }
  591. if nf_swaped in flags then
  592. begin
  593. if (nodetype=slashn) then
  594. op:=A_FDIVRP
  595. else if (nodetype=subn) then
  596. op:=A_FSUBRP;
  597. end;
  598. { to avoid the pentium bug
  599. if (op=FDIVP) and (opt_processors=pentium) then
  600. cg.a_call_name(exprasmlist,'EMUL_FDIVP')
  601. else
  602. }
  603. { the Intel assemblers want operands }
  604. if op<>A_FCOMPP then
  605. begin
  606. r.enum:=R_ST;
  607. r2.enum:=R_ST1;
  608. emit_reg_reg(op,S_NO,r,r2);
  609. dec(trgcpu(rg).fpuvaroffset);
  610. end
  611. else
  612. begin
  613. emit_none(op,S_NO);
  614. dec(trgcpu(rg).fpuvaroffset,2);
  615. end;
  616. { on comparison load flags }
  617. if cmpop then
  618. begin
  619. if not(R_EAX in rg.unusedregsint) then
  620. begin
  621. rg.getexplicitregisterint(exprasmlist,R_EDI);
  622. r.enum:=R_EAX;
  623. r2.enum:=R_EDI;
  624. emit_reg_reg(A_MOV,S_L,r,r2);
  625. end;
  626. r.enum:=R_AX;
  627. emit_reg(A_FNSTSW,S_NO,r);
  628. emit_none(A_SAHF,S_NO);
  629. if not(R_EAX in rg.unusedregsint) then
  630. begin
  631. r.enum:=R_EAX;
  632. r2.enum:=R_EDI;
  633. emit_reg_reg(A_MOV,S_L,r2,r);
  634. rg.ungetregisterint(exprasmlist,r2);
  635. end;
  636. if nf_swaped in flags then
  637. begin
  638. case nodetype of
  639. equaln : resflags:=F_E;
  640. unequaln : resflags:=F_NE;
  641. ltn : resflags:=F_A;
  642. lten : resflags:=F_AE;
  643. gtn : resflags:=F_B;
  644. gten : resflags:=F_BE;
  645. end;
  646. end
  647. else
  648. begin
  649. case nodetype of
  650. equaln : resflags:=F_E;
  651. unequaln : resflags:=F_NE;
  652. ltn : resflags:=F_B;
  653. lten : resflags:=F_BE;
  654. gtn : resflags:=F_A;
  655. gten : resflags:=F_AE;
  656. end;
  657. end;
  658. location_reset(location,LOC_FLAGS,OS_NO);
  659. location.resflags:=resflags;
  660. end
  661. else
  662. begin
  663. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  664. location.register.enum:=R_ST;
  665. end;
  666. end;
  667. {*****************************************************************************
  668. AddSmallSet
  669. *****************************************************************************}
  670. procedure ti386addnode.second_addsmallset;
  671. var
  672. opsize : TOpSize;
  673. op : TAsmOp;
  674. cmpop,
  675. pushedfpu,
  676. extra_not,
  677. noswap : boolean;
  678. begin
  679. pass_left_and_right(pushedfpu);
  680. { when a setdef is passed, it has to be a smallset }
  681. if ((left.resulttype.def.deftype=setdef) and
  682. (tsetdef(left.resulttype.def).settype<>smallset)) or
  683. ((right.resulttype.def.deftype=setdef) and
  684. (tsetdef(right.resulttype.def).settype<>smallset)) then
  685. internalerror(200203301);
  686. cmpop:=false;
  687. noswap:=false;
  688. extra_not:=false;
  689. opsize:=S_L;
  690. case nodetype of
  691. addn :
  692. begin
  693. { this is a really ugly hack!!!!!!!!!! }
  694. { this could be done later using EDI }
  695. { as it is done for subn }
  696. { instead of two registers!!!! }
  697. { adding elements is not commutative }
  698. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  699. swapleftright;
  700. { are we adding set elements ? }
  701. if right.nodetype=setelementn then
  702. begin
  703. { no range support for smallsets! }
  704. if assigned(tsetelementnode(right).right) then
  705. internalerror(43244);
  706. { bts requires both elements to be registers }
  707. location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],false);
  708. location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],true);
  709. op:=A_BTS;
  710. noswap:=true;
  711. end
  712. else
  713. op:=A_OR;
  714. end;
  715. symdifn :
  716. op:=A_XOR;
  717. muln :
  718. op:=A_AND;
  719. subn :
  720. begin
  721. op:=A_AND;
  722. if (not(nf_swaped in flags)) and
  723. (right.location.loc=LOC_CONSTANT) then
  724. right.location.value := not(right.location.value)
  725. else if (nf_swaped in flags) and
  726. (left.location.loc=LOC_CONSTANT) then
  727. left.location.value := not(left.location.value)
  728. else
  729. extra_not:=true;
  730. end;
  731. equaln,
  732. unequaln :
  733. begin
  734. op:=A_CMP;
  735. cmpop:=true;
  736. end;
  737. lten,gten:
  738. begin
  739. If (not(nf_swaped in flags) and
  740. (nodetype = lten)) or
  741. ((nf_swaped in flags) and
  742. (nodetype = gten)) then
  743. swapleftright;
  744. location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],true);
  745. emit_op_right_left(A_AND,opsize);
  746. op:=A_CMP;
  747. cmpop:=true;
  748. { warning: ugly hack, we need a JE so change the node to equaln }
  749. nodetype:=equaln;
  750. end;
  751. xorn :
  752. op:=A_XOR;
  753. orn :
  754. op:=A_OR;
  755. andn :
  756. op:=A_AND;
  757. else
  758. begin
  759. { no < or > support for sets }
  760. CGMessage(type_e_mismatch);
  761. end;
  762. end;
  763. { left must be a register }
  764. left_must_be_reg(opsize,noswap);
  765. emit_generic_code(op,opsize,true,extra_not,false);
  766. location_freetemp(exprasmlist,right.location);
  767. location_release(exprasmlist,right.location);
  768. if cmpop then
  769. begin
  770. location_freetemp(exprasmlist,left.location);
  771. location_release(exprasmlist,left.location);
  772. end;
  773. set_result_location(cmpop,true);
  774. end;
  775. {*****************************************************************************
  776. Add64bit
  777. *****************************************************************************}
  778. procedure ti386addnode.second_add64bit;
  779. var
  780. op : TOpCG;
  781. op1,op2 : TAsmOp;
  782. opsize : TOpSize;
  783. hregister,
  784. hregister2 : tregister;
  785. href : treference;
  786. hl4 : tasmlabel;
  787. pushedfpu,
  788. mboverflow,
  789. cmpop,
  790. unsigned : boolean;
  791. r:Tregister;
  792. procedure firstjmp64bitcmp;
  793. var
  794. oldnodetype : tnodetype;
  795. begin
  796. load_all_regvars(exprasmlist);
  797. { the jump the sequence is a little bit hairy }
  798. case nodetype of
  799. ltn,gtn:
  800. begin
  801. emitjmp(flags_to_cond(getresflags(unsigned)),truelabel);
  802. { cheat a little bit for the negative test }
  803. toggleflag(nf_swaped);
  804. emitjmp(flags_to_cond(getresflags(unsigned)),falselabel);
  805. toggleflag(nf_swaped);
  806. end;
  807. lten,gten:
  808. begin
  809. oldnodetype:=nodetype;
  810. if nodetype=lten then
  811. nodetype:=ltn
  812. else
  813. nodetype:=gtn;
  814. emitjmp(flags_to_cond(getresflags(unsigned)),truelabel);
  815. { cheat for the negative test }
  816. if nodetype=ltn then
  817. nodetype:=gtn
  818. else
  819. nodetype:=ltn;
  820. emitjmp(flags_to_cond(getresflags(unsigned)),falselabel);
  821. nodetype:=oldnodetype;
  822. end;
  823. equaln:
  824. emitjmp(C_NE,falselabel);
  825. unequaln:
  826. emitjmp(C_NE,truelabel);
  827. end;
  828. end;
  829. procedure secondjmp64bitcmp;
  830. begin
  831. { the jump the sequence is a little bit hairy }
  832. case nodetype of
  833. ltn,gtn,lten,gten:
  834. begin
  835. { the comparisaion of the low dword have to be }
  836. { always unsigned! }
  837. emitjmp(flags_to_cond(getresflags(true)),truelabel);
  838. cg.a_jmp_always(exprasmlist,falselabel);
  839. end;
  840. equaln:
  841. begin
  842. emitjmp(C_NE,falselabel);
  843. cg.a_jmp_always(exprasmlist,truelabel);
  844. end;
  845. unequaln:
  846. begin
  847. emitjmp(C_NE,truelabel);
  848. cg.a_jmp_always(exprasmlist,falselabel);
  849. end;
  850. end;
  851. end;
  852. begin
  853. firstcomplex(self);
  854. pass_left_and_right(pushedfpu);
  855. op1:=A_NONE;
  856. op2:=A_NONE;
  857. mboverflow:=false;
  858. cmpop:=false;
  859. opsize:=S_L;
  860. unsigned:=((left.resulttype.def.deftype=orddef) and
  861. (torddef(left.resulttype.def).typ=u64bit)) or
  862. ((right.resulttype.def.deftype=orddef) and
  863. (torddef(right.resulttype.def).typ=u64bit));
  864. case nodetype of
  865. addn :
  866. begin
  867. op:=OP_ADD;
  868. mboverflow:=true;
  869. end;
  870. subn :
  871. begin
  872. op:=OP_SUB;
  873. op1:=A_SUB;
  874. op2:=A_SBB;
  875. mboverflow:=true;
  876. end;
  877. ltn,lten,
  878. gtn,gten,
  879. equaln,unequaln:
  880. begin
  881. op:=OP_NONE;
  882. cmpop:=true;
  883. end;
  884. xorn:
  885. op:=OP_XOR;
  886. orn:
  887. op:=OP_OR;
  888. andn:
  889. op:=OP_AND;
  890. muln:
  891. begin
  892. { should be handled in pass_1 (JM) }
  893. internalerror(200109051);
  894. end;
  895. else
  896. CGMessage(type_e_mismatch);
  897. end;
  898. { left and right no register? }
  899. { then one must be demanded }
  900. if (left.location.loc<>LOC_REGISTER) then
  901. begin
  902. if (right.location.loc<>LOC_REGISTER) then
  903. begin
  904. { we can reuse a CREGISTER for comparison }
  905. if not((left.location.loc=LOC_CREGISTER) and cmpop) then
  906. begin
  907. if (left.location.loc<>LOC_CREGISTER) then
  908. begin
  909. location_freetemp(exprasmlist,left.location);
  910. location_release(exprasmlist,left.location);
  911. end;
  912. hregister:=rg.getregisterint(exprasmlist);
  913. hregister2:=rg.getregisterint(exprasmlist);
  914. cg64.a_load64_loc_reg(exprasmlist,left.location,joinreg64(hregister,hregister2));
  915. location_reset(left.location,LOC_REGISTER,OS_64);
  916. left.location.registerlow:=hregister;
  917. left.location.registerhigh:=hregister2;
  918. end;
  919. end
  920. else
  921. begin
  922. location_swap(left.location,right.location);
  923. toggleflag(nf_swaped);
  924. end;
  925. end;
  926. { at this point, left.location.loc should be LOC_REGISTER }
  927. if right.location.loc=LOC_REGISTER then
  928. begin
  929. { when swapped another result register }
  930. if (nodetype=subn) and (nf_swaped in flags) then
  931. begin
  932. cg64.a_op64_reg_reg(exprasmlist,op,
  933. left.location.register64,
  934. right.location.register64);
  935. location_swap(left.location,right.location);
  936. toggleflag(nf_swaped);
  937. end
  938. else if cmpop then
  939. begin
  940. emit_reg_reg(A_CMP,S_L,right.location.registerhigh,left.location.registerhigh);
  941. firstjmp64bitcmp;
  942. emit_reg_reg(A_CMP,S_L,right.location.registerlow,left.location.registerlow);
  943. secondjmp64bitcmp;
  944. end
  945. else
  946. begin
  947. cg64.a_op64_reg_reg(exprasmlist,op,
  948. right.location.register64,
  949. left.location.register64);
  950. end;
  951. location_release(exprasmlist,right.location);
  952. end
  953. else
  954. begin
  955. { right.location<>LOC_REGISTER }
  956. if (nodetype=subn) and (nf_swaped in flags) then
  957. begin
  958. r.enum:=R_EDI;
  959. rg.getexplicitregisterint(exprasmlist,R_EDI);
  960. cg64.a_load64low_loc_reg(exprasmlist,right.location,r);
  961. emit_reg_reg(op1,opsize,left.location.registerlow,r);
  962. emit_reg_reg(A_MOV,opsize,r,left.location.registerlow);
  963. cg64.a_load64high_loc_reg(exprasmlist,right.location,r);
  964. { the carry flag is still ok }
  965. emit_reg_reg(op2,opsize,left.location.registerhigh,r);
  966. emit_reg_reg(A_MOV,opsize,r,left.location.registerhigh);
  967. rg.ungetregisterint(exprasmlist,r);
  968. if right.location.loc<>LOC_CREGISTER then
  969. begin
  970. location_freetemp(exprasmlist,right.location);
  971. location_release(exprasmlist,right.location);
  972. end;
  973. end
  974. else if cmpop then
  975. begin
  976. case right.location.loc of
  977. LOC_CREGISTER :
  978. begin
  979. emit_reg_reg(A_CMP,S_L,right.location.registerhigh,left.location.registerhigh);
  980. firstjmp64bitcmp;
  981. emit_reg_reg(A_CMP,S_L,right.location.registerlow,left.location.registerlow);
  982. secondjmp64bitcmp;
  983. end;
  984. LOC_CREFERENCE,
  985. LOC_REFERENCE :
  986. begin
  987. href:=right.location.reference;
  988. inc(href.offset,4);
  989. emit_ref_reg(A_CMP,S_L,href,left.location.registerhigh);
  990. firstjmp64bitcmp;
  991. emit_ref_reg(A_CMP,S_L,right.location.reference,left.location.registerlow);
  992. secondjmp64bitcmp;
  993. cg.a_jmp_always(exprasmlist,falselabel);
  994. location_freetemp(exprasmlist,right.location);
  995. location_release(exprasmlist,right.location);
  996. end;
  997. LOC_CONSTANT :
  998. begin
  999. exprasmlist.concat(taicpu.op_const_reg(A_CMP,S_L,hi(right.location.valueqword),left.location.registerhigh));
  1000. firstjmp64bitcmp;
  1001. exprasmlist.concat(taicpu.op_const_reg(A_CMP,S_L,lo(right.location.valueqword),left.location.registerlow));
  1002. secondjmp64bitcmp;
  1003. end;
  1004. else
  1005. internalerror(200203282);
  1006. end;
  1007. end
  1008. else
  1009. begin
  1010. cg64.a_op64_loc_reg(exprasmlist,op,right.location,
  1011. left.location.register64);
  1012. if (right.location.loc<>LOC_CREGISTER) then
  1013. begin
  1014. location_freetemp(exprasmlist,right.location);
  1015. location_release(exprasmlist,right.location);
  1016. end;
  1017. end;
  1018. end;
  1019. if (left.location.loc<>LOC_CREGISTER) and cmpop then
  1020. begin
  1021. location_freetemp(exprasmlist,left.location);
  1022. location_release(exprasmlist,left.location);
  1023. end;
  1024. { only in case of overflow operations }
  1025. { produce overflow code }
  1026. { we must put it here directly, because sign of operation }
  1027. { is in unsigned VAR!! }
  1028. if mboverflow then
  1029. begin
  1030. if cs_check_overflow in aktlocalswitches then
  1031. begin
  1032. objectlibrary.getlabel(hl4);
  1033. if unsigned then
  1034. emitjmp(C_NB,hl4)
  1035. else
  1036. emitjmp(C_NO,hl4);
  1037. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  1038. cg.a_label(exprasmlist,hl4);
  1039. end;
  1040. end;
  1041. { we have LOC_JUMP as result }
  1042. if cmpop then
  1043. location_reset(location,LOC_JUMP,OS_NO)
  1044. else
  1045. location_copy(location,left.location);
  1046. end;
  1047. {*****************************************************************************
  1048. AddMMX
  1049. *****************************************************************************}
  1050. {$ifdef SUPPORT_MMX}
  1051. procedure ti386addnode.second_addmmx;
  1052. var
  1053. op : TAsmOp;
  1054. pushedfpu,
  1055. cmpop : boolean;
  1056. mmxbase : tmmxtype;
  1057. r,hregister : tregister;
  1058. begin
  1059. pass_left_and_right(pushedfpu);
  1060. cmpop:=false;
  1061. mmxbase:=mmx_type(left.resulttype.def);
  1062. case nodetype of
  1063. addn :
  1064. begin
  1065. if (cs_mmx_saturation in aktlocalswitches) then
  1066. begin
  1067. case mmxbase of
  1068. mmxs8bit:
  1069. op:=A_PADDSB;
  1070. mmxu8bit:
  1071. op:=A_PADDUSB;
  1072. mmxs16bit,mmxfixed16:
  1073. op:=A_PADDSB;
  1074. mmxu16bit:
  1075. op:=A_PADDUSW;
  1076. end;
  1077. end
  1078. else
  1079. begin
  1080. case mmxbase of
  1081. mmxs8bit,mmxu8bit:
  1082. op:=A_PADDB;
  1083. mmxs16bit,mmxu16bit,mmxfixed16:
  1084. op:=A_PADDW;
  1085. mmxs32bit,mmxu32bit:
  1086. op:=A_PADDD;
  1087. end;
  1088. end;
  1089. end;
  1090. muln :
  1091. begin
  1092. case mmxbase of
  1093. mmxs16bit,mmxu16bit:
  1094. op:=A_PMULLW;
  1095. mmxfixed16:
  1096. op:=A_PMULHW;
  1097. end;
  1098. end;
  1099. subn :
  1100. begin
  1101. if (cs_mmx_saturation in aktlocalswitches) then
  1102. begin
  1103. case mmxbase of
  1104. mmxs8bit:
  1105. op:=A_PSUBSB;
  1106. mmxu8bit:
  1107. op:=A_PSUBUSB;
  1108. mmxs16bit,mmxfixed16:
  1109. op:=A_PSUBSB;
  1110. mmxu16bit:
  1111. op:=A_PSUBUSW;
  1112. end;
  1113. end
  1114. else
  1115. begin
  1116. case mmxbase of
  1117. mmxs8bit,mmxu8bit:
  1118. op:=A_PSUBB;
  1119. mmxs16bit,mmxu16bit,mmxfixed16:
  1120. op:=A_PSUBW;
  1121. mmxs32bit,mmxu32bit:
  1122. op:=A_PSUBD;
  1123. end;
  1124. end;
  1125. end;
  1126. xorn:
  1127. op:=A_PXOR;
  1128. orn:
  1129. op:=A_POR;
  1130. andn:
  1131. op:=A_PAND;
  1132. else
  1133. CGMessage(type_e_mismatch);
  1134. end;
  1135. { left and right no register? }
  1136. { then one must be demanded }
  1137. if (left.location.loc<>LOC_MMXREGISTER) then
  1138. begin
  1139. if (right.location.loc=LOC_MMXREGISTER) then
  1140. begin
  1141. location_swap(left.location,right.location);
  1142. toggleflag(nf_swaped);
  1143. end
  1144. else
  1145. begin
  1146. { register variable ? }
  1147. if (left.location.loc=LOC_CMMXREGISTER) then
  1148. begin
  1149. hregister:=rg.getregistermm(exprasmlist);
  1150. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1151. end
  1152. else
  1153. begin
  1154. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1155. internalerror(200203245);
  1156. location_release(exprasmlist,left.location);
  1157. hregister:=rg.getregistermm(exprasmlist);
  1158. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1159. end;
  1160. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1161. left.location.register:=hregister;
  1162. end;
  1163. end;
  1164. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1165. if right.location.loc<>LOC_MMXREGISTER then
  1166. begin
  1167. if (nodetype=subn) and (nf_swaped in flags) then
  1168. begin
  1169. r.enum:=R_MM7;
  1170. if right.location.loc=LOC_CMMXREGISTER then
  1171. begin
  1172. emit_reg_reg(A_MOVQ,S_NO,right.location.register,r);
  1173. emit_reg_reg(op,S_NO,left.location.register,r);
  1174. emit_reg_reg(A_MOVQ,S_NO,r,left.location.register);
  1175. end
  1176. else
  1177. begin
  1178. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1179. internalerror(200203247);
  1180. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,r);
  1181. emit_reg_reg(op,S_NO,left.location.register,r);
  1182. emit_reg_reg(A_MOVQ,S_NO,r,left.location.register);
  1183. location_release(exprasmlist,right.location);
  1184. end;
  1185. end
  1186. else
  1187. begin
  1188. if (right.location.loc=LOC_CMMXREGISTER) then
  1189. begin
  1190. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1191. end
  1192. else
  1193. begin
  1194. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1195. internalerror(200203246);
  1196. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1197. location_release(exprasmlist,right.location);
  1198. end;
  1199. end;
  1200. end
  1201. else
  1202. begin
  1203. { right.location=LOC_MMXREGISTER }
  1204. if (nodetype=subn) and (nf_swaped in flags) then
  1205. begin
  1206. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1207. location_swap(left.location,right.location);
  1208. toggleflag(nf_swaped);
  1209. end
  1210. else
  1211. begin
  1212. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1213. end;
  1214. end;
  1215. location_freetemp(exprasmlist,right.location);
  1216. location_release(exprasmlist,right.location);
  1217. if cmpop then
  1218. begin
  1219. location_freetemp(exprasmlist,left.location);
  1220. location_release(exprasmlist,left.location);
  1221. end;
  1222. set_result_location(cmpop,true);
  1223. end;
  1224. {$endif SUPPORT_MMX}
  1225. {*****************************************************************************
  1226. pass_2
  1227. *****************************************************************************}
  1228. procedure ti386addnode.pass_2;
  1229. { is also being used for xor, and "mul", "sub, or and comparative }
  1230. { operators }
  1231. var
  1232. popeax,popedx,
  1233. pushedfpu,
  1234. mboverflow,cmpop : boolean;
  1235. op : tasmop;
  1236. power : longint;
  1237. opsize : topsize;
  1238. { true, if unsigned types are compared }
  1239. unsigned : boolean;
  1240. { is_in_dest if the result is put directly into }
  1241. { the resulting refernce or varregister }
  1242. {is_in_dest : boolean;}
  1243. { true, if for sets subtractions the extra not should generated }
  1244. extra_not : boolean;
  1245. regstopush: tregisterset;
  1246. r:Tregister;
  1247. begin
  1248. { to make it more readable, string and set (not smallset!) have their
  1249. own procedures }
  1250. case left.resulttype.def.deftype of
  1251. orddef :
  1252. begin
  1253. { handling boolean expressions }
  1254. if is_boolean(left.resulttype.def) and
  1255. is_boolean(right.resulttype.def) then
  1256. begin
  1257. second_addboolean;
  1258. exit;
  1259. end
  1260. { 64bit operations }
  1261. else if is_64bitint(left.resulttype.def) then
  1262. begin
  1263. second_add64bit;
  1264. exit;
  1265. end;
  1266. end;
  1267. stringdef :
  1268. begin
  1269. second_addstring;
  1270. exit;
  1271. end;
  1272. setdef :
  1273. begin
  1274. { normalsets are already handled in pass1 }
  1275. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1276. internalerror(200109041);
  1277. second_addsmallset;
  1278. exit;
  1279. end;
  1280. arraydef :
  1281. begin
  1282. {$ifdef SUPPORT_MMX}
  1283. if is_mmx_able_array(left.resulttype.def) then
  1284. begin
  1285. second_addmmx;
  1286. exit;
  1287. end;
  1288. {$endif SUPPORT_MMX}
  1289. end;
  1290. floatdef :
  1291. begin
  1292. second_addfloat;
  1293. exit;
  1294. end;
  1295. end;
  1296. { defaults }
  1297. {is_in_dest:=false;}
  1298. extra_not:=false;
  1299. mboverflow:=false;
  1300. cmpop:=false;
  1301. unsigned:=not(is_signed(left.resulttype.def)) or
  1302. not(is_signed(right.resulttype.def));
  1303. opsize:=def_opsize(left.resulttype.def);
  1304. pass_left_and_right(pushedfpu);
  1305. if (left.resulttype.def.deftype=pointerdef) or
  1306. (right.resulttype.def.deftype=pointerdef) or
  1307. (is_class_or_interface(right.resulttype.def) and is_class_or_interface(left.resulttype.def)) or
  1308. (left.resulttype.def.deftype=classrefdef) or
  1309. (left.resulttype.def.deftype=procvardef) or
  1310. ((left.resulttype.def.deftype=enumdef) and
  1311. (left.resulttype.def.size=4)) or
  1312. ((left.resulttype.def.deftype=orddef) and
  1313. (torddef(left.resulttype.def).typ in [s32bit,u32bit])) or
  1314. ((right.resulttype.def.deftype=orddef) and
  1315. (torddef(right.resulttype.def).typ in [s32bit,u32bit])) then
  1316. begin
  1317. case nodetype of
  1318. addn :
  1319. begin
  1320. op:=A_ADD;
  1321. mboverflow:=true;
  1322. end;
  1323. muln :
  1324. begin
  1325. if unsigned then
  1326. op:=A_MUL
  1327. else
  1328. op:=A_IMUL;
  1329. mboverflow:=true;
  1330. end;
  1331. subn :
  1332. begin
  1333. op:=A_SUB;
  1334. mboverflow:=true;
  1335. end;
  1336. ltn,lten,
  1337. gtn,gten,
  1338. equaln,unequaln :
  1339. begin
  1340. op:=A_CMP;
  1341. cmpop:=true;
  1342. end;
  1343. xorn :
  1344. op:=A_XOR;
  1345. orn :
  1346. op:=A_OR;
  1347. andn :
  1348. op:=A_AND;
  1349. else
  1350. CGMessage(type_e_mismatch);
  1351. end;
  1352. { filter MUL, which requires special handling }
  1353. if op=A_MUL then
  1354. begin
  1355. popeax:=false;
  1356. popedx:=false;
  1357. { here you need to free the symbol first }
  1358. { left.location and right.location must }
  1359. { only be freed when they are really released, }
  1360. { because the optimizer NEEDS correct regalloc }
  1361. { info!!! (JM) }
  1362. { the location.register will be filled in later (JM) }
  1363. location_reset(location,LOC_REGISTER,OS_INT);
  1364. regstopush := all_registers;
  1365. remove_non_regvars_from_loc(right.location,regstopush);
  1366. remove_non_regvars_from_loc(left.location,regstopush);
  1367. { now, regstopush does NOT contain EAX and/or EDX if they are }
  1368. { used in either the left or the right location, excepts if }
  1369. {they are regvars. It DOES contain them if they are used in }
  1370. { another location (JM) }
  1371. if not(R_EAX in rg.unusedregsint) and
  1372. (R_EAX in regstopush) then
  1373. begin
  1374. r.enum:=R_EAX;
  1375. emit_reg(A_PUSH,S_L,r);
  1376. popeax:=true;
  1377. end;
  1378. if not(R_EDX in rg.unusedregsint) and
  1379. (R_EDX in regstopush) then
  1380. begin
  1381. r.enum:=R_EDX;
  1382. emit_reg(A_PUSH,S_L,r);
  1383. popedx:=true;
  1384. end;
  1385. { left.location can be R_EAX !!! }
  1386. r.enum:=R_EDI;
  1387. rg.getexplicitregisterint(exprasmlist,R_EDI);
  1388. { load the left value }
  1389. cg.a_load_loc_reg(exprasmlist,left.location,r);
  1390. location_release(exprasmlist,left.location);
  1391. { allocate EAX }
  1392. r.enum:=R_EAX;
  1393. if R_EAX in rg.unusedregsint then
  1394. exprasmList.concat(tai_regalloc.Alloc(r));
  1395. { load he right value }
  1396. cg.a_load_loc_reg(exprasmlist,right.location,r);
  1397. location_release(exprasmlist,right.location);
  1398. { allocate EAX if it isn't yet allocated (JM) }
  1399. if (R_EAX in rg.unusedregsint) then
  1400. exprasmList.concat(tai_regalloc.Alloc(r));
  1401. { also allocate EDX, since it is also modified by }
  1402. { a mul (JM) }
  1403. r.enum:=R_EDX;
  1404. if R_EDX in rg.unusedregsint then
  1405. exprasmList.concat(tai_regalloc.Alloc(r));
  1406. r.enum:=R_EDI;
  1407. emit_reg(A_MUL,S_L,r);
  1408. rg.ungetregisterint(exprasmlist,r);
  1409. r.enum:=R_EDX;
  1410. if R_EDX in rg.unusedregsint then
  1411. exprasmList.concat(tai_regalloc.DeAlloc(r));
  1412. r.enum:=R_EAX;
  1413. if R_EAX in rg.unusedregsint then
  1414. exprasmList.concat(tai_regalloc.DeAlloc(r));
  1415. location.register:=rg.getregisterint(exprasmlist);
  1416. r.enum:=R_EAX;
  1417. emit_reg_reg(A_MOV,S_L,r,location.register);
  1418. r.enum:=R_EDX;
  1419. if popedx then
  1420. emit_reg(A_POP,S_L,r);
  1421. r.enum:=R_EAX;
  1422. if popeax then
  1423. emit_reg(A_POP,S_L,r);
  1424. location_freetemp(exprasmlist,left.location);
  1425. location_freetemp(exprasmlist,right.location);
  1426. exit;
  1427. end;
  1428. { Convert flags to register first }
  1429. if (left.location.loc=LOC_FLAGS) then
  1430. location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],false);
  1431. if (right.location.loc=LOC_FLAGS) then
  1432. location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
  1433. left_must_be_reg(opsize,false);
  1434. emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
  1435. location_freetemp(exprasmlist,right.location);
  1436. location_release(exprasmlist,right.location);
  1437. if cmpop and
  1438. (left.location.loc<>LOC_CREGISTER) then
  1439. begin
  1440. location_freetemp(exprasmlist,left.location);
  1441. location_release(exprasmlist,left.location);
  1442. end;
  1443. set_result_location(cmpop,unsigned);
  1444. end
  1445. { 8/16 bit enum,char,wchar types }
  1446. else
  1447. if ((left.resulttype.def.deftype=orddef) and
  1448. (torddef(left.resulttype.def).typ in [uchar,uwidechar])) or
  1449. ((left.resulttype.def.deftype=enumdef) and
  1450. ((left.resulttype.def.size=1) or
  1451. (left.resulttype.def.size=2))) then
  1452. begin
  1453. case nodetype of
  1454. ltn,lten,gtn,gten,
  1455. equaln,unequaln :
  1456. cmpop:=true;
  1457. else
  1458. CGMessage(type_e_mismatch);
  1459. end;
  1460. left_must_be_reg(opsize,false);
  1461. emit_op_right_left(A_CMP,opsize);
  1462. location_freetemp(exprasmlist,right.location);
  1463. location_release(exprasmlist,right.location);
  1464. if left.location.loc<>LOC_CREGISTER then
  1465. begin
  1466. location_freetemp(exprasmlist,left.location);
  1467. location_release(exprasmlist,left.location);
  1468. end;
  1469. set_result_location(true,true);
  1470. end
  1471. else
  1472. CGMessage(type_e_mismatch);
  1473. end;
  1474. begin
  1475. caddnode:=ti386addnode;
  1476. end.
  1477. {
  1478. $Log$
  1479. Revision 1.53 2003-01-08 18:43:57 daniel
  1480. * Tregister changed into a record
  1481. Revision 1.52 2002/11/25 17:43:26 peter
  1482. * splitted defbase in defutil,symutil,defcmp
  1483. * merged isconvertable and is_equal into compare_defs(_ext)
  1484. * made operator search faster by walking the list only once
  1485. Revision 1.51 2002/11/15 01:58:56 peter
  1486. * merged changes from 1.0.7 up to 04-11
  1487. - -V option for generating bug report tracing
  1488. - more tracing for option parsing
  1489. - errors for cdecl and high()
  1490. - win32 import stabs
  1491. - win32 records<=8 are returned in eax:edx (turned off by default)
  1492. - heaptrc update
  1493. - more info for temp management in .s file with EXTDEBUG
  1494. Revision 1.50 2002/10/20 13:11:27 jonas
  1495. * re-enabled optimized version of comparisons with the empty string that
  1496. I accidentally disabled in revision 1.26
  1497. Revision 1.49 2002/08/23 16:14:49 peter
  1498. * tempgen cleanup
  1499. * tt_noreuse temp type added that will be used in genentrycode
  1500. Revision 1.48 2002/08/14 18:41:48 jonas
  1501. - remove valuelow/valuehigh fields from tlocation, because they depend
  1502. on the endianess of the host operating system -> difficult to get
  1503. right. Use lo/hi(location.valueqword) instead (remember to use
  1504. valueqword and not value!!)
  1505. Revision 1.47 2002/08/11 14:32:29 peter
  1506. * renamed current_library to objectlibrary
  1507. Revision 1.46 2002/08/11 13:24:16 peter
  1508. * saving of asmsymbols in ppu supported
  1509. * asmsymbollist global is removed and moved into a new class
  1510. tasmlibrarydata that will hold the info of a .a file which
  1511. corresponds with a single module. Added librarydata to tmodule
  1512. to keep the library info stored for the module. In the future the
  1513. objectfiles will also be stored to the tasmlibrarydata class
  1514. * all getlabel/newasmsymbol and friends are moved to the new class
  1515. Revision 1.45 2002/07/26 11:17:52 jonas
  1516. * the optimization of converting a multiplication with a power of two to
  1517. a shl is moved from n386add/secondpass to nadd/resulttypepass
  1518. Revision 1.44 2002/07/20 11:58:00 florian
  1519. * types.pas renamed to defbase.pas because D6 contains a types
  1520. unit so this would conflicts if D6 programms are compiled
  1521. + Willamette/SSE2 instructions to assembler added
  1522. Revision 1.43 2002/07/11 14:41:32 florian
  1523. * start of the new generic parameter handling
  1524. Revision 1.42 2002/07/07 09:52:33 florian
  1525. * powerpc target fixed, very simple units can be compiled
  1526. * some basic stuff for better callparanode handling, far from being finished
  1527. Revision 1.41 2002/07/01 18:46:31 peter
  1528. * internal linker
  1529. * reorganized aasm layer
  1530. Revision 1.40 2002/07/01 16:23:55 peter
  1531. * cg64 patch
  1532. * basics for currency
  1533. * asnode updates for class and interface (not finished)
  1534. Revision 1.39 2002/05/18 13:34:22 peter
  1535. * readded missing revisions
  1536. Revision 1.38 2002/05/16 19:46:51 carl
  1537. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1538. + try to fix temp allocation (still in ifdef)
  1539. + generic constructor calls
  1540. + start of tassembler / tmodulebase class cleanup
  1541. Revision 1.36 2002/05/13 19:54:37 peter
  1542. * removed n386ld and n386util units
  1543. * maybe_save/maybe_restore added instead of the old maybe_push
  1544. Revision 1.35 2002/05/12 16:53:17 peter
  1545. * moved entry and exitcode to ncgutil and cgobj
  1546. * foreach gets extra argument for passing local data to the
  1547. iterator function
  1548. * -CR checks also class typecasts at runtime by changing them
  1549. into as
  1550. * fixed compiler to cycle with the -CR option
  1551. * fixed stabs with elf writer, finally the global variables can
  1552. be watched
  1553. * removed a lot of routines from cga unit and replaced them by
  1554. calls to cgobj
  1555. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1556. u32bit then the other is typecasted also to u32bit without giving
  1557. a rangecheck warning/error.
  1558. * fixed pascal calling method with reversing also the high tree in
  1559. the parast, detected by tcalcst3 test
  1560. Revision 1.34 2002/04/25 20:16:40 peter
  1561. * moved more routines from cga/n386util
  1562. Revision 1.33 2002/04/05 15:09:13 jonas
  1563. * fixed web bug 1915
  1564. Revision 1.32 2002/04/04 19:06:10 peter
  1565. * removed unused units
  1566. * use tlocation.size in cg.a_*loc*() routines
  1567. Revision 1.31 2002/04/02 17:11:35 peter
  1568. * tlocation,treference update
  1569. * LOC_CONSTANT added for better constant handling
  1570. * secondadd splitted in multiple routines
  1571. * location_force_reg added for loading a location to a register
  1572. of a specified size
  1573. * secondassignment parses now first the right and then the left node
  1574. (this is compatible with Kylix). This saves a lot of push/pop especially
  1575. with string operations
  1576. * adapted some routines to use the new cg methods
  1577. Revision 1.29 2002/03/04 19:10:13 peter
  1578. * removed compiler warnings
  1579. }