n386add.pas 58 KB

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