n386cal.pas 14 KB

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