n386cal.pas 12 KB

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