2
0

n386add.pas 62 KB

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