n386add.pas 62 KB

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