n386cal.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate i386 assembler for in call 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 n386cal;
  19. {$i fpcdefs.inc}
  20. interface
  21. { $define AnsiStrRef}
  22. uses
  23. ncgcal;
  24. type
  25. ti386callnode = class(tcgcallnode)
  26. protected
  27. function align_parasize(parasize,para_alignment:longint):longint;override;
  28. procedure pop_parasize(pop_size:longint);override;
  29. procedure extra_interrupt_code;override;
  30. end;
  31. implementation
  32. uses
  33. globtype,systems,
  34. cutils,verbose,globals,
  35. symconst,symbase,symdef,symsym,symtable,defutil,
  36. {$ifdef GDB}
  37. {$ifdef delphi}
  38. sysutils,
  39. {$else}
  40. strings,
  41. {$endif}
  42. gdb,
  43. {$endif GDB}
  44. cginfo,cgbase,pass_2,
  45. cpubase,paramgr,
  46. aasmbase,aasmtai,aasmcpu,
  47. node,ncal,nbas,nmem,nld,ncnv,
  48. ncgutil,cga,cgobj,tgobj,rgobj,rgcpu,cgcpu,cpuinfo;
  49. {*****************************************************************************
  50. TI386CALLNODE
  51. *****************************************************************************}
  52. procedure ti386callnode.extra_interrupt_code;
  53. var
  54. r : Tregister;
  55. begin
  56. emit_none(A_PUSHF,S_L);
  57. r.enum:=R_CS;
  58. emit_reg(A_PUSH,S_L,r);
  59. end;
  60. function ti386callnode.align_parasize(parasize,para_alignment:longint):longint;
  61. var
  62. pop_size : longint;
  63. {$ifdef OPTALIGN}
  64. pop_esp : boolean;
  65. push_size : longint;
  66. {$endif OPTALIGN}
  67. i : integer;
  68. rsp : tregister;
  69. begin
  70. pop_size:=0;
  71. { Old pushedsize aligned on 4 ? }
  72. i:=parasize and 3;
  73. if i>0 then
  74. inc(pop_size,4-i);
  75. { This parasize aligned on 4 ? }
  76. i:=procdefinition.para_size(para_alignment) and 3;
  77. if i>0 then
  78. inc(pop_size,4-i);
  79. { insert the opcode and update pushedparasize }
  80. { never push 4 or more !! }
  81. pop_size:=pop_size mod 4;
  82. if pop_size>0 then
  83. begin
  84. inc(pushedparasize,pop_size);
  85. rsp.enum:=R_INTREGISTER;
  86. rsp.number:=NR_ESP;
  87. exprasmlist.concat(taicpu.op_const_reg(A_SUB,S_L,pop_size,rsp));
  88. {$ifdef GDB}
  89. if (cs_debuginfo in aktmoduleswitches) and
  90. (exprasmList.first=exprasmList.last) then
  91. exprasmList.concat(Tai_force_line.Create);
  92. {$endif GDB}
  93. end;
  94. {$ifdef OPTALIGN}
  95. if pop_allowed and (cs_align in aktglobalswitches) then
  96. begin
  97. pop_esp:=true;
  98. push_size:=procdefinition.para_size(para_alignment);
  99. { !!!! here we have to take care of return type, self
  100. and nested procedures
  101. }
  102. inc(push_size,12);
  103. emit_reg_reg(A_MOV,S_L,rsp,R_EDI);
  104. if (push_size mod 8)=0 then
  105. emit_const_reg(A_AND,S_L,$fffffff8,rsp)
  106. else
  107. begin
  108. emit_const_reg(A_SUB,S_L,push_size,rsp);
  109. emit_const_reg(A_AND,S_L,$fffffff8,rsp);
  110. emit_const_reg(A_SUB,S_L,push_size,rsp);
  111. end;
  112. r.enum:=R_INTREGISTER;
  113. r.number:=R_EDI;
  114. emit_reg(A_PUSH,S_L,r);
  115. end
  116. else
  117. pop_esp:=false;
  118. {$endif OPTALIGN}
  119. align_parasize:=pop_size;
  120. end;
  121. procedure ti386callnode.pop_parasize(pop_size:longint);
  122. var
  123. hreg : tregister;
  124. begin
  125. { better than an add on all processors }
  126. if pop_size=4 then
  127. begin
  128. {$ifdef newra}
  129. hreg:=rg.getregisterint(exprasmlist,OS_INT);
  130. {$else}
  131. hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
  132. {$endif}
  133. exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
  134. {$ifdef newra}
  135. rg.ungetregisterint(exprasmlist,hreg);
  136. {$else}
  137. cg.free_scratch_reg(exprasmlist,hreg);
  138. {$endif newra}
  139. end
  140. { the pentium has two pipes and pop reg is pairable }
  141. { but the registers must be different! }
  142. else
  143. if (pop_size=8) and
  144. not(cs_littlesize in aktglobalswitches) and
  145. (aktoptprocessor=ClassP5)
  146. {$ifndef newra} and (rg.countunusedregsint>0){$endif} then
  147. begin
  148. {$ifdef newra}
  149. hreg:=rg.getregisterint(exprasmlist,OS_INT);
  150. {$else}
  151. hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
  152. {$endif}
  153. exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
  154. {$ifdef newra}
  155. rg.ungetregisterint(exprasmlist,hreg);
  156. {$else}
  157. cg.free_scratch_reg(exprasmlist,hreg);
  158. {$endif}
  159. hreg:=rg.getregisterint(exprasmlist,OS_INT);
  160. exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
  161. rg.ungetregisterint(exprasmlist,hreg);
  162. end
  163. else
  164. if pop_size<>0 then
  165. begin
  166. hreg.enum:=R_INTREGISTER;
  167. hreg.number:=NR_ESP;
  168. exprasmlist.concat(taicpu.op_const_reg(A_ADD,S_L,pop_size,hreg));
  169. end;
  170. {$ifdef OPTALIGN}
  171. if pop_esp then
  172. emit_reg(A_POP,S_L,rsp);
  173. {$endif OPTALIGN}
  174. end;
  175. begin
  176. ccallnode:=ti386callnode;
  177. end.
  178. {
  179. $Log$
  180. Revision 1.90 2003-04-23 14:42:08 daniel
  181. * Further register allocator work. Compiler now smaller with new
  182. allocator than without.
  183. * Somebody forgot to adjust ppu version number
  184. Revision 1.89 2003/04/22 14:33:38 peter
  185. * removed some notes/hints
  186. Revision 1.88 2003/04/22 10:09:35 daniel
  187. + Implemented the actual register allocator
  188. + Scratch registers unavailable when new register allocator used
  189. + maybe_save/maybe_restore unavailable when new register allocator used
  190. Revision 1.87 2003/04/04 15:38:56 peter
  191. * moved generic code from n386cal to ncgcal, i386 now also
  192. uses the generic ncgcal
  193. Revision 1.86 2003/03/30 20:59:07 peter
  194. * fix classmethod from classmethod call
  195. * move BeforeDestruction/AfterConstruction calls to
  196. genentrycode/genexitcode instead of generating them on the fly
  197. after a call to a constructor
  198. Revision 1.85 2003/03/28 19:16:57 peter
  199. * generic constructor working for i386
  200. * remove fixed self register
  201. * esi added as address register for i386
  202. Revision 1.84 2003/03/13 19:52:23 jonas
  203. * and more new register allocator fixes (in the i386 code generator this
  204. time). At least now the ppc cross compiler can compile the linux
  205. system unit again, but I haven't tested it.
  206. Revision 1.83 2003/03/06 11:35:50 daniel
  207. * Fixed internalerror 7843 issue
  208. Revision 1.82 2003/02/19 22:00:15 daniel
  209. * Code generator converted to new register notation
  210. - Horribily outdated todo.txt removed
  211. Revision 1.81 2003/01/30 21:46:57 peter
  212. * self fixes for static methods (merged)
  213. Revision 1.80 2003/01/13 18:37:44 daniel
  214. * Work on register conversion
  215. Revision 1.79 2003/01/08 18:43:57 daniel
  216. * Tregister changed into a record
  217. Revision 1.78 2002/12/15 21:30:12 florian
  218. * tcallnode.paraitem introduced, all references to defcoll removed
  219. Revision 1.77 2002/11/27 20:05:06 peter
  220. * cdecl array of const fixes
  221. Revision 1.76 2002/11/25 17:43:26 peter
  222. * splitted defbase in defutil,symutil,defcmp
  223. * merged isconvertable and is_equal into compare_defs(_ext)
  224. * made operator search faster by walking the list only once
  225. Revision 1.75 2002/11/18 17:32:00 peter
  226. * pass proccalloption to ret_in_xxx and push_xxx functions
  227. Revision 1.74 2002/11/15 01:58:57 peter
  228. * merged changes from 1.0.7 up to 04-11
  229. - -V option for generating bug report tracing
  230. - more tracing for option parsing
  231. - errors for cdecl and high()
  232. - win32 import stabs
  233. - win32 records<=8 are returned in eax:edx (turned off by default)
  234. - heaptrc update
  235. - more info for temp management in .s file with EXTDEBUG
  236. Revision 1.73 2002/10/05 12:43:29 carl
  237. * fixes for Delphi 6 compilation
  238. (warning : Some features do not work under Delphi)
  239. Revision 1.72 2002/09/17 18:54:03 jonas
  240. * a_load_reg_reg() now has two size parameters: source and dest. This
  241. allows some optimizations on architectures that don't encode the
  242. register size in the register name.
  243. Revision 1.71 2002/09/16 19:07:37 peter
  244. * push 0 instead of VMT when calling a constructor from a member
  245. Revision 1.70 2002/09/07 15:25:10 peter
  246. * old logs removed and tabs fixed
  247. Revision 1.69 2002/09/01 18:43:27 peter
  248. * include accumulator in regs_to_push list
  249. Revision 1.68 2002/09/01 12:13:00 peter
  250. * use a_call_reg
  251. * ungetiftemp for procvar of object temp
  252. Revision 1.67 2002/08/25 19:25:21 peter
  253. * sym.insert_in_data removed
  254. * symtable.insertvardata/insertconstdata added
  255. * removed insert_in_data call from symtable.insert, it needs to be
  256. called separatly. This allows to deref the address calculation
  257. * procedures now calculate the parast addresses after the procedure
  258. directives are parsed. This fixes the cdecl parast problem
  259. * push_addr_param has an extra argument that specifies if cdecl is used
  260. or not
  261. Revision 1.66 2002/08/23 16:14:49 peter
  262. * tempgen cleanup
  263. * tt_noreuse temp type added that will be used in genentrycode
  264. Revision 1.65 2002/08/18 20:06:30 peter
  265. * inlining is now also allowed in interface
  266. * renamed write/load to ppuwrite/ppuload
  267. * tnode storing in ppu
  268. * nld,ncon,nbas are already updated for storing in ppu
  269. Revision 1.64 2002/08/17 09:23:45 florian
  270. * first part of procinfo rewrite
  271. Revision 1.63 2002/08/12 15:08:42 carl
  272. + stab register indexes for powerpc (moved from gdb to cpubase)
  273. + tprocessor enumeration moved to cpuinfo
  274. + linker in target_info is now a class
  275. * many many updates for m68k (will soon start to compile)
  276. - removed some ifdef or correct them for correct cpu
  277. Revision 1.62 2002/08/11 14:32:30 peter
  278. * renamed current_library to objectlibrary
  279. Revision 1.61 2002/08/11 13:24:16 peter
  280. * saving of asmsymbols in ppu supported
  281. * asmsymbollist global is removed and moved into a new class
  282. tasmlibrarydata that will hold the info of a .a file which
  283. corresponds with a single module. Added librarydata to tmodule
  284. to keep the library info stored for the module. In the future the
  285. objectfiles will also be stored to the tasmlibrarydata class
  286. * all getlabel/newasmsymbol and friends are moved to the new class
  287. Revision 1.60 2002/07/20 11:58:01 florian
  288. * types.pas renamed to defbase.pas because D6 contains a types
  289. unit so this would conflicts if D6 programms are compiled
  290. + Willamette/SSE2 instructions to assembler added
  291. Revision 1.59 2002/07/11 14:41:33 florian
  292. * start of the new generic parameter handling
  293. Revision 1.58 2002/07/07 09:52:34 florian
  294. * powerpc target fixed, very simple units can be compiled
  295. * some basic stuff for better callparanode handling, far from being finished
  296. Revision 1.57 2002/07/06 20:27:26 carl
  297. + generic set handling
  298. Revision 1.56 2002/07/01 18:46:31 peter
  299. * internal linker
  300. * reorganized aasm layer
  301. Revision 1.55 2002/07/01 16:23:56 peter
  302. * cg64 patch
  303. * basics for currency
  304. * asnode updates for class and interface (not finished)
  305. Revision 1.54 2002/05/20 13:30:40 carl
  306. * bugfix of hdisponen (base must be set, not index)
  307. * more portability fixes
  308. Revision 1.53 2002/05/18 13:34:23 peter
  309. * readded missing revisions
  310. Revision 1.52 2002/05/16 19:46:51 carl
  311. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  312. + try to fix temp allocation (still in ifdef)
  313. + generic constructor calls
  314. + start of tassembler / tmodulebase class cleanup
  315. Revision 1.50 2002/05/13 19:54:38 peter
  316. * removed n386ld and n386util units
  317. * maybe_save/maybe_restore added instead of the old maybe_push
  318. Revision 1.49 2002/05/12 16:53:17 peter
  319. * moved entry and exitcode to ncgutil and cgobj
  320. * foreach gets extra argument for passing local data to the
  321. iterator function
  322. * -CR checks also class typecasts at runtime by changing them
  323. into as
  324. * fixed compiler to cycle with the -CR option
  325. * fixed stabs with elf writer, finally the global variables can
  326. be watched
  327. * removed a lot of routines from cga unit and replaced them by
  328. calls to cgobj
  329. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  330. u32bit then the other is typecasted also to u32bit without giving
  331. a rangecheck warning/error.
  332. * fixed pascal calling method with reversing also the high tree in
  333. the parast, detected by tcalcst3 test
  334. }