n386add.pas 59 KB

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