n386add.pas 62 KB

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