n386add.pas 62 KB

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