n386mat.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate i386 assembler for math nodes
  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 n386mat;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nmat,ncgmat;
  23. type
  24. ti386moddivnode = class(tmoddivnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386shlshrnode = class(tshlshrnode)
  28. procedure pass_2;override;
  29. { everything will be handled in pass_2 }
  30. function first_shlshr64bitint: tnode; override;
  31. end;
  32. ti386unaryminusnode = class(tcgunaryminusnode)
  33. {$ifdef SUPPORT_MMX}
  34. procedure second_mmx;override;
  35. {$endif SUPPORT_MMX}
  36. procedure second_float;override;
  37. function pass_1:tnode;override;
  38. end;
  39. ti386notnode = class(tcgnotnode)
  40. procedure second_boolean;override;
  41. {$ifdef SUPPORT_MMX}
  42. procedure second_mmx;override;
  43. {$endif SUPPORT_MMX}
  44. end;
  45. implementation
  46. uses
  47. globtype,systems,
  48. cutils,verbose,globals,
  49. symconst,symdef,aasmbase,aasmtai,defutil,
  50. cgbase,pass_1,pass_2,
  51. ncon,
  52. cpubase,cpuinfo,
  53. cga,ncgutil,cgobj;
  54. {*****************************************************************************
  55. TI386MODDIVNODE
  56. *****************************************************************************}
  57. procedure ti386moddivnode.pass_2;
  58. var hreg1,hreg2:Tregister;
  59. power:longint;
  60. hl:Tasmlabel;
  61. op:Tasmop;
  62. begin
  63. secondpass(left);
  64. if codegenerror then
  65. exit;
  66. secondpass(right);
  67. if codegenerror then
  68. exit;
  69. if is_64bitint(resulttype.def) then
  70. { should be handled in pass_1 (JM) }
  71. internalerror(200109052);
  72. { put numerator in register }
  73. location_reset(location,LOC_REGISTER,OS_INT);
  74. location_force_reg(exprasmlist,left.location,OS_INT,false);
  75. hreg1:=left.location.register;
  76. if (nodetype=divn) and (right.nodetype=ordconstn) and
  77. ispowerof2(tordconstnode(right).value,power) then
  78. begin
  79. { for signed numbers, the numerator must be adjusted before the
  80. shift instruction, but not wih unsigned numbers! Otherwise,
  81. "Cardinal($ffffffff) div 16" overflows! (JM) }
  82. if is_signed(left.resulttype.def) Then
  83. begin
  84. if (aktOptProcessor <> class386) and
  85. not(cs_littlesize in aktglobalswitches) then
  86. { use a sequence without jumps, saw this in
  87. comp.compilers (JM) }
  88. begin
  89. { no jumps, but more operations }
  90. hreg2:=cg.getintregister(exprasmlist,OS_INT);
  91. emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
  92. {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
  93. emit_const_reg(A_SAR,S_L,31,hreg2);
  94. {If signed, hreg2=right value-1, otherwise 0.}
  95. emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
  96. { add to the left value }
  97. emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
  98. { release EDX if we used it }
  99. cg.ungetregister(exprasmlist,hreg2);
  100. { do the shift }
  101. emit_const_reg(A_SAR,S_L,power,hreg1);
  102. end
  103. else
  104. begin
  105. { a jump, but less operations }
  106. emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
  107. objectlibrary.getlabel(hl);
  108. cg.a_jmp_flags(exprasmlist,F_NS,hl);
  109. if power=1 then
  110. emit_reg(A_INC,S_L,hreg1)
  111. else
  112. emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
  113. cg.a_label(exprasmlist,hl);
  114. emit_const_reg(A_SAR,S_L,power,hreg1);
  115. end
  116. end
  117. else
  118. emit_const_reg(A_SHR,S_L,power,hreg1);
  119. location.register:=hreg1;
  120. end
  121. else
  122. begin
  123. {Bring denominator to a register.}
  124. cg.ungetregister(exprasmlist,hreg1);
  125. cg.getexplicitregister(exprasmlist,NR_EAX);
  126. emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
  127. cg.getexplicitregister(exprasmlist,NR_EDX);
  128. {Sign extension depends on the left type.}
  129. if torddef(left.resulttype.def).typ=u32bit then
  130. emit_reg_reg(A_XOR,S_L,NR_EDX,NR_EDX)
  131. else
  132. emit_none(A_CDQ,S_NO);
  133. {Division depends on the right type.}
  134. if Torddef(right.resulttype.def).typ=u32bit then
  135. op:=A_DIV
  136. else
  137. op:=A_IDIV;
  138. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  139. emit_ref(op,S_L,right.location.reference)
  140. else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  141. emit_reg(op,S_L,right.location.register)
  142. else
  143. begin
  144. hreg1:=cg.getintregister(exprasmlist,right.location.size);
  145. cg.a_load_loc_reg(exprasmlist,OS_32,right.location,hreg1);
  146. cg.ungetregister(exprasmlist,hreg1);
  147. emit_reg(op,S_L,hreg1);
  148. end;
  149. location_release(exprasmlist,right.location);
  150. {Copy the result into a new register. Release EAX & EDX.}
  151. if nodetype=divn then
  152. begin
  153. cg.ungetregister(exprasmlist,NR_EDX);
  154. cg.ungetregister(exprasmlist,NR_EAX);
  155. location.register:=cg.getintregister(exprasmlist,OS_INT);
  156. emit_reg_reg(A_MOV,S_L,NR_EAX,location.register);
  157. end
  158. else
  159. begin
  160. cg.ungetregister(exprasmlist,NR_EAX);
  161. cg.ungetregister(exprasmlist,NR_EDX);
  162. location.register:=cg.getintregister(exprasmlist,OS_INT);
  163. emit_reg_reg(A_MOV,S_L,NR_EDX,location.register);
  164. end;
  165. end;
  166. end;
  167. {*****************************************************************************
  168. TI386SHLRSHRNODE
  169. *****************************************************************************}
  170. function ti386shlshrnode.first_shlshr64bitint: tnode;
  171. begin
  172. result := nil;
  173. end;
  174. procedure ti386shlshrnode.pass_2;
  175. var hregisterhigh,hregisterlow:Tregister;
  176. op:Tasmop;
  177. l1,l2,l3:Tasmlabel;
  178. begin
  179. secondpass(left);
  180. secondpass(right);
  181. { determine operator }
  182. if nodetype=shln then
  183. op:=A_SHL
  184. else
  185. op:=A_SHR;
  186. if is_64bitint(left.resulttype.def) then
  187. begin
  188. location_reset(location,LOC_REGISTER,OS_64);
  189. { load left operator in a register }
  190. location_force_reg(exprasmlist,left.location,OS_64,false);
  191. hregisterhigh:=left.location.registerhigh;
  192. hregisterlow:=left.location.registerlow;
  193. { shifting by a constant directly coded: }
  194. if (right.nodetype=ordconstn) then
  195. begin
  196. { shrd/shl works only for values <=31 !! }
  197. if Tordconstnode(right).value>63 then
  198. begin
  199. cg.a_load_const_reg(exprasmlist,OS_32,0,hregisterhigh);
  200. cg.a_load_const_reg(exprasmlist,OS_32,0,hregisterlow);
  201. location.registerlow:=hregisterlow;
  202. location.registerhigh:=hregisterhigh;
  203. end
  204. else if Tordconstnode(right).value>31 then
  205. begin
  206. if nodetype=shln then
  207. begin
  208. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  209. if ((tordconstnode(right).value and 31) <> 0) then
  210. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  211. hregisterlow);
  212. end
  213. else
  214. begin
  215. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  216. if ((tordconstnode(right).value and 31) <> 0) then
  217. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  218. hregisterhigh);
  219. end;
  220. location.registerhigh:=hregisterlow;
  221. location.registerlow:=hregisterhigh;
  222. end
  223. else
  224. begin
  225. if nodetype=shln then
  226. begin
  227. emit_const_reg_reg(A_SHLD,S_L,tordconstnode(right).value and 31,
  228. hregisterlow,hregisterhigh);
  229. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  230. hregisterlow);
  231. end
  232. else
  233. begin
  234. emit_const_reg_reg(A_SHRD,S_L,tordconstnode(right).value and 31,
  235. hregisterhigh,hregisterlow);
  236. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  237. hregisterhigh);
  238. end;
  239. location.registerlow:=hregisterlow;
  240. location.registerhigh:=hregisterhigh;
  241. end;
  242. end
  243. else
  244. begin
  245. { load right operators in a register }
  246. cg.getexplicitregister(exprasmlist,NR_ECX);
  247. cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
  248. if right.location.loc<>LOC_CREGISTER then
  249. location_release(exprasmlist,right.location);
  250. { left operator is already in a register }
  251. { hence are both in a register }
  252. { is it in the case ECX ? }
  253. { the damned shift instructions work only til a count of 32 }
  254. { so we've to do some tricks here }
  255. objectlibrary.getlabel(l1);
  256. objectlibrary.getlabel(l2);
  257. objectlibrary.getlabel(l3);
  258. emit_const_reg(A_CMP,S_L,64,NR_ECX);
  259. cg.a_jmp_flags(exprasmlist,F_L,l1);
  260. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  261. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  262. cg.a_jmp_always(exprasmlist,l3);
  263. cg.a_label(exprasmlist,l1);
  264. emit_const_reg(A_CMP,S_L,32,NR_ECX);
  265. cg.a_jmp_flags(exprasmlist,F_L,l2);
  266. emit_const_reg(A_SUB,S_L,32,NR_ECX);
  267. if nodetype=shln then
  268. begin
  269. emit_reg_reg(A_SHL,S_L,NR_CL,hregisterlow);
  270. emit_reg_reg(A_MOV,S_L,hregisterlow,hregisterhigh);
  271. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  272. cg.a_jmp_always(exprasmlist,l3);
  273. cg.a_label(exprasmlist,l2);
  274. emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hregisterlow,hregisterhigh);
  275. emit_reg_reg(A_SHL,S_L,NR_CL,hregisterlow);
  276. end
  277. else
  278. begin
  279. emit_reg_reg(A_SHR,S_L,NR_CL,hregisterhigh);
  280. emit_reg_reg(A_MOV,S_L,hregisterhigh,hregisterlow);
  281. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  282. cg.a_jmp_always(exprasmlist,l3);
  283. cg.a_label(exprasmlist,l2);
  284. emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hregisterhigh,hregisterlow);
  285. emit_reg_reg(A_SHR,S_L,NR_CL,hregisterhigh);
  286. end;
  287. cg.a_label(exprasmlist,l3);
  288. cg.ungetregister(exprasmlist,NR_ECX);
  289. location.registerlow:=hregisterlow;
  290. location.registerhigh:=hregisterhigh;
  291. end;
  292. end
  293. else
  294. begin
  295. { load left operators in a register }
  296. location_copy(location,left.location);
  297. location_force_reg(exprasmlist,location,OS_INT,false);
  298. { shifting by a constant directly coded: }
  299. if (right.nodetype=ordconstn) then
  300. { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
  301. emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
  302. else
  303. begin
  304. { load right operators in a ECX }
  305. if right.location.loc<>LOC_CREGISTER then
  306. location_release(exprasmlist,right.location);
  307. cg.getexplicitregister(exprasmlist,NR_ECX);
  308. cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
  309. { right operand is in ECX }
  310. cg.ungetregister(exprasmlist,NR_ECX);
  311. emit_reg_reg(op,S_L,NR_CL,location.register);
  312. end;
  313. end;
  314. end;
  315. {*****************************************************************************
  316. TI386UNARYMINUSNODE
  317. *****************************************************************************}
  318. function ti386unaryminusnode.pass_1 : tnode;
  319. begin
  320. result:=nil;
  321. firstpass(left);
  322. if codegenerror then
  323. exit;
  324. if (left.resulttype.def.deftype=floatdef) then
  325. begin
  326. if (registersfpu < 1) then
  327. registersfpu := 1;
  328. expectloc:=LOC_FPUREGISTER;
  329. end
  330. {$ifdef SUPPORT_MMX}
  331. else
  332. if (cs_mmx in aktlocalswitches) and
  333. is_mmx_able_array(left.resulttype.def) then
  334. begin
  335. registers32:=left.registers32;
  336. registersfpu:=left.registersfpu;
  337. registersmmx:=left.registersmmx;
  338. if (left.location.loc<>LOC_MMXREGISTER) and
  339. (registersmmx<1) then
  340. registersmmx:=1;
  341. end
  342. {$endif SUPPORT_MMX}
  343. else
  344. inherited pass_1;
  345. end;
  346. {$ifdef SUPPORT_MMX}
  347. procedure ti386unaryminusnode.second_mmx;
  348. var
  349. op : tasmop;
  350. hreg : tregister;
  351. begin
  352. secondpass(left);
  353. location_reset(location,LOC_MMXREGISTER,OS_NO);
  354. hreg:=cg.getmmxregister(exprasmlist,OS_M64);
  355. emit_reg_reg(A_PXOR,S_NO,hreg,hreg);
  356. case left.location.loc of
  357. LOC_MMXREGISTER:
  358. begin
  359. location.register:=left.location.register;
  360. end;
  361. LOC_CMMXREGISTER:
  362. begin
  363. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  364. emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
  365. end;
  366. LOC_REFERENCE,
  367. LOC_CREFERENCE:
  368. begin
  369. reference_release(exprasmlist,left.location.reference);
  370. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  371. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
  372. end;
  373. else
  374. internalerror(200203225);
  375. end;
  376. if cs_mmx_saturation in aktlocalswitches then
  377. case mmx_type(resulttype.def) of
  378. mmxs8bit:
  379. op:=A_PSUBSB;
  380. mmxu8bit:
  381. op:=A_PSUBUSB;
  382. mmxs16bit,mmxfixed16:
  383. op:=A_PSUBSW;
  384. mmxu16bit:
  385. op:=A_PSUBUSW;
  386. end
  387. else
  388. case mmx_type(resulttype.def) of
  389. mmxs8bit,mmxu8bit:
  390. op:=A_PSUBB;
  391. mmxs16bit,mmxu16bit,mmxfixed16:
  392. op:=A_PSUBW;
  393. mmxs32bit,mmxu32bit:
  394. op:=A_PSUBD;
  395. end;
  396. emit_reg_reg(op,S_NO,location.register,hreg);
  397. cg.ungetregister(exprasmlist,hreg);
  398. emit_reg_reg(A_MOVQ,S_NO,hreg,location.register);
  399. end;
  400. {$endif SUPPORT_MMX}
  401. procedure ti386unaryminusnode.second_float;
  402. begin
  403. secondpass(left);
  404. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  405. case left.location.loc of
  406. LOC_REFERENCE,
  407. LOC_CREFERENCE:
  408. begin
  409. reference_release(exprasmlist,left.location.reference);
  410. location.register:=NR_ST;
  411. cg.a_loadfpu_ref_reg(exprasmlist,
  412. def_cgsize(left.resulttype.def),
  413. left.location.reference,location.register);
  414. emit_none(A_FCHS,S_NO);
  415. end;
  416. LOC_FPUREGISTER,
  417. LOC_CFPUREGISTER:
  418. begin
  419. { "load st,st" is ignored by the code generator }
  420. cg.a_loadfpu_reg_reg(exprasmlist,left.location.size,left.location.register,NR_ST);
  421. location.register:=NR_ST;
  422. emit_none(A_FCHS,S_NO);
  423. end;
  424. end;
  425. end;
  426. {*****************************************************************************
  427. TI386NOTNODE
  428. *****************************************************************************}
  429. procedure ti386notnode.second_boolean;
  430. var
  431. hl : tasmlabel;
  432. opsize : topsize;
  433. begin
  434. opsize:=def_opsize(resulttype.def);
  435. if left.expectloc=LOC_JUMP then
  436. begin
  437. location_reset(location,LOC_JUMP,OS_NO);
  438. hl:=truelabel;
  439. truelabel:=falselabel;
  440. falselabel:=hl;
  441. secondpass(left);
  442. maketojumpbool(exprasmlist,left,lr_load_regvars);
  443. hl:=truelabel;
  444. truelabel:=falselabel;
  445. falselabel:=hl;
  446. end
  447. else
  448. begin
  449. { the second pass could change the location of left }
  450. { if it is a register variable, so we've to do }
  451. { this before the case statement }
  452. secondpass(left);
  453. case left.expectloc of
  454. LOC_FLAGS :
  455. begin
  456. location_release(exprasmlist,left.location);
  457. location_reset(location,LOC_FLAGS,OS_NO);
  458. location.resflags:=left.location.resflags;
  459. inverse_flags(location.resflags);
  460. end;
  461. LOC_CONSTANT,
  462. LOC_REGISTER,
  463. LOC_CREGISTER,
  464. LOC_REFERENCE,
  465. LOC_CREFERENCE :
  466. begin
  467. location_force_reg(exprasmlist,left.location,def_cgsize(resulttype.def),true);
  468. location_release(exprasmlist,left.location);
  469. emit_reg_reg(A_TEST,opsize,left.location.register,left.location.register);
  470. location_reset(location,LOC_FLAGS,OS_NO);
  471. location.resflags:=F_E;
  472. end;
  473. else
  474. internalerror(200203224);
  475. end;
  476. end;
  477. end;
  478. {$ifdef SUPPORT_MMX}
  479. procedure ti386notnode.second_mmx;
  480. var hreg,r:Tregister;
  481. begin
  482. secondpass(left);
  483. location_reset(location,LOC_MMXREGISTER,OS_NO);
  484. r:=cg.getintregister(exprasmlist,OS_INT);
  485. emit_const_reg(A_MOV,S_L,longint($ffffffff),r);
  486. { load operand }
  487. case left.location.loc of
  488. LOC_MMXREGISTER:
  489. location_copy(location,left.location);
  490. LOC_CMMXREGISTER:
  491. begin
  492. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  493. emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
  494. end;
  495. LOC_REFERENCE,
  496. LOC_CREFERENCE:
  497. begin
  498. location_release(exprasmlist,left.location);
  499. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  500. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
  501. end;
  502. end;
  503. { load mask }
  504. hreg:=cg.getmmxregister(exprasmlist,OS_M64);
  505. emit_reg_reg(A_MOVD,S_NO,r,hreg);
  506. cg.ungetregister(exprasmlist,r);
  507. { lower 32 bit }
  508. emit_reg_reg(A_PXOR,S_D,hreg,location.register);
  509. { shift mask }
  510. emit_const_reg(A_PSLLQ,S_NO,32,hreg);
  511. { higher 32 bit }
  512. cg.ungetregister(exprasmlist,hreg);
  513. emit_reg_reg(A_PXOR,S_D,hreg,location.register);
  514. end;
  515. {$endif SUPPORT_MMX}
  516. begin
  517. cmoddivnode:=ti386moddivnode;
  518. cshlshrnode:=ti386shlshrnode;
  519. cunaryminusnode:=ti386unaryminusnode;
  520. cnotnode:=ti386notnode;
  521. end.
  522. {
  523. $Log$
  524. Revision 1.66 2003-12-10 17:28:41 peter
  525. * int64 shl/shr > 63 returns 0
  526. Revision 1.65 2003/10/10 17:48:14 peter
  527. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  528. * tregisteralloctor renamed to trgobj
  529. * removed rgobj from a lot of units
  530. * moved location_* and reference_* to cgobj
  531. * first things for mmx register allocation
  532. Revision 1.64 2003/10/09 21:31:37 daniel
  533. * Register allocator splitted, ans abstract now
  534. Revision 1.63 2003/10/01 20:34:49 peter
  535. * procinfo unit contains tprocinfo
  536. * cginfo renamed to cgbase
  537. * moved cgmessage to verbose
  538. * fixed ppc and sparc compiles
  539. Revision 1.62 2003/09/29 20:58:56 peter
  540. * optimized releasing of registers
  541. Revision 1.61 2003/09/28 21:48:20 peter
  542. * fix register leaks
  543. Revision 1.60 2003/09/03 15:55:01 peter
  544. * NEWRA branch merged
  545. Revision 1.59.2.2 2003/08/31 13:50:16 daniel
  546. * Remove sorting and use pregenerated indexes
  547. * Some work on making things compile
  548. Revision 1.59.2.1 2003/08/29 17:29:00 peter
  549. * next batch of updates
  550. Revision 1.59 2003/07/02 22:18:04 peter
  551. * paraloc splitted in callerparaloc,calleeparaloc
  552. * sparc calling convention updates
  553. Revision 1.58 2003/06/13 21:19:31 peter
  554. * current_procdef removed, use current_procinfo.procdef instead
  555. Revision 1.57 2003/06/03 21:11:09 peter
  556. * cg.a_load_* get a from and to size specifier
  557. * makeregsize only accepts newregister
  558. * i386 uses generic tcgnotnode,tcgunaryminus
  559. Revision 1.56 2003/06/03 13:01:59 daniel
  560. * Register allocator finished
  561. Revision 1.55 2003/05/31 15:04:31 peter
  562. * load_loc_reg update
  563. Revision 1.54 2003/05/22 21:32:29 peter
  564. * removed some unit dependencies
  565. Revision 1.53 2003/04/22 23:50:23 peter
  566. * firstpass uses expectloc
  567. * checks if there are differences between the expectloc and
  568. location.loc from secondpass in EXTDEBUG
  569. Revision 1.52 2003/04/22 14:33:38 peter
  570. * removed some notes/hints
  571. Revision 1.51 2003/04/22 10:09:35 daniel
  572. + Implemented the actual register allocator
  573. + Scratch registers unavailable when new register allocator used
  574. + maybe_save/maybe_restore unavailable when new register allocator used
  575. Revision 1.50 2003/04/21 19:15:26 peter
  576. * when ecx is not available allocated another register
  577. Revision 1.49 2003/04/17 10:02:48 daniel
  578. * Tweaked register allocate/deallocate positition to less interferences
  579. are generated.
  580. Revision 1.48 2003/03/28 19:16:57 peter
  581. * generic constructor working for i386
  582. * remove fixed self register
  583. * esi added as address register for i386
  584. Revision 1.47 2003/03/08 20:36:41 daniel
  585. + Added newra version of Ti386shlshrnode
  586. + Added interference graph construction code
  587. Revision 1.46 2003/03/08 13:59:17 daniel
  588. * Work to handle new register notation in ag386nsm
  589. + Added newra version of Ti386moddivnode
  590. Revision 1.45 2003/02/19 22:00:15 daniel
  591. * Code generator converted to new register notation
  592. - Horribily outdated todo.txt removed
  593. Revision 1.44 2003/01/13 18:37:44 daniel
  594. * Work on register conversion
  595. Revision 1.43 2003/01/13 14:54:34 daniel
  596. * Further work to convert codegenerator register convention;
  597. internalerror bug fixed.
  598. Revision 1.42 2003/01/08 18:43:57 daniel
  599. * Tregister changed into a record
  600. Revision 1.41 2002/11/25 17:43:26 peter
  601. * splitted defbase in defutil,symutil,defcmp
  602. * merged isconvertable and is_equal into compare_defs(_ext)
  603. * made operator search faster by walking the list only once
  604. Revision 1.40 2002/09/07 15:25:10 peter
  605. * old logs removed and tabs fixed
  606. Revision 1.39 2002/08/15 15:15:55 carl
  607. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  608. * more generic nodes for maths
  609. * several fixes for better m68k support
  610. Revision 1.38 2002/08/14 19:18:16 carl
  611. * bugfix of unaryminus node with left LOC_CREGISTER
  612. Revision 1.37 2002/08/12 15:08:42 carl
  613. + stab register indexes for powerpc (moved from gdb to cpubase)
  614. + tprocessor enumeration moved to cpuinfo
  615. + linker in target_info is now a class
  616. * many many updates for m68k (will soon start to compile)
  617. - removed some ifdef or correct them for correct cpu
  618. Revision 1.36 2002/08/11 14:32:30 peter
  619. * renamed current_library to objectlibrary
  620. Revision 1.35 2002/08/11 13:24:17 peter
  621. * saving of asmsymbols in ppu supported
  622. * asmsymbollist global is removed and moved into a new class
  623. tasmlibrarydata that will hold the info of a .a file which
  624. corresponds with a single module. Added librarydata to tmodule
  625. to keep the library info stored for the module. In the future the
  626. objectfiles will also be stored to the tasmlibrarydata class
  627. * all getlabel/newasmsymbol and friends are moved to the new class
  628. Revision 1.34 2002/08/02 07:44:31 jonas
  629. * made assigned() handling generic
  630. * add nodes now can also evaluate constant expressions at compile time
  631. that contain nil nodes
  632. Revision 1.33 2002/07/20 11:58:02 florian
  633. * types.pas renamed to defbase.pas because D6 contains a types
  634. unit so this would conflicts if D6 programms are compiled
  635. + Willamette/SSE2 instructions to assembler added
  636. Revision 1.32 2002/07/01 18:46:33 peter
  637. * internal linker
  638. * reorganized aasm layer
  639. Revision 1.31 2002/05/18 13:34:25 peter
  640. * readded missing revisions
  641. Revision 1.30 2002/05/16 19:46:51 carl
  642. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  643. + try to fix temp allocation (still in ifdef)
  644. + generic constructor calls
  645. + start of tassembler / tmodulebase class cleanup
  646. Revision 1.28 2002/05/13 19:54:38 peter
  647. * removed n386ld and n386util units
  648. * maybe_save/maybe_restore added instead of the old maybe_push
  649. Revision 1.27 2002/05/12 16:53:17 peter
  650. * moved entry and exitcode to ncgutil and cgobj
  651. * foreach gets extra argument for passing local data to the
  652. iterator function
  653. * -CR checks also class typecasts at runtime by changing them
  654. into as
  655. * fixed compiler to cycle with the -CR option
  656. * fixed stabs with elf writer, finally the global variables can
  657. be watched
  658. * removed a lot of routines from cga unit and replaced them by
  659. calls to cgobj
  660. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  661. u32bit then the other is typecasted also to u32bit without giving
  662. a rangecheck warning/error.
  663. * fixed pascal calling method with reversing also the high tree in
  664. the parast, detected by tcalcst3 test
  665. Revision 1.26 2002/04/04 19:06:12 peter
  666. * removed unused units
  667. * use tlocation.size in cg.a_*loc*() routines
  668. Revision 1.25 2002/04/02 17:11:36 peter
  669. * tlocation,treference update
  670. * LOC_CONSTANT added for better constant handling
  671. * secondadd splitted in multiple routines
  672. * location_force_reg added for loading a location to a register
  673. of a specified size
  674. * secondassignment parses now first the right and then the left node
  675. (this is compatible with Kylix). This saves a lot of push/pop especially
  676. with string operations
  677. * adapted some routines to use the new cg methods
  678. Revision 1.24 2002/03/31 20:26:39 jonas
  679. + a_loadfpu_* and a_loadmm_* methods in tcg
  680. * register allocation is now handled by a class and is mostly processor
  681. independent (+rgobj.pas and i386/rgcpu.pas)
  682. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  683. * some small improvements and fixes to the optimizer
  684. * some register allocation fixes
  685. * some fpuvaroffset fixes in the unary minus node
  686. * push/popusedregisters is now called rg.save/restoreusedregisters and
  687. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  688. also better optimizable)
  689. * fixed and optimized register saving/restoring for new/dispose nodes
  690. * LOC_FPU locations now also require their "register" field to be set to
  691. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  692. - list field removed of the tnode class because it's not used currently
  693. and can cause hard-to-find bugs
  694. Revision 1.23 2002/03/04 19:10:14 peter
  695. * removed compiler warnings
  696. }