n386cnv.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate i386 assembler for type converting 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 n386cnv;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,ncgcnv,defutil,defcmp,nx86cnv;
  23. type
  24. ti386typeconvnode = class(tx86typeconvnode)
  25. protected
  26. { procedure second_int_to_int;override; }
  27. { procedure second_string_to_string;override; }
  28. { procedure second_cstring_to_pchar;override; }
  29. { procedure second_string_to_chararray;override; }
  30. { procedure second_array_to_pointer;override; }
  31. { procedure second_pointer_to_array;override; }
  32. { procedure second_chararray_to_string;override; }
  33. { procedure second_char_to_string;override; }
  34. function first_int_to_real: tnode; override;
  35. procedure second_int_to_real;override;
  36. { procedure second_real_to_real;override; }
  37. { procedure second_cord_to_pointer;override; }
  38. { procedure second_proc_to_procvar;override; }
  39. { procedure second_bool_to_int;override; }
  40. { procedure second_int_to_bool;override; }
  41. { procedure second_load_smallset;override; }
  42. { procedure second_ansistring_to_pchar;override; }
  43. { procedure second_pchar_to_string;override; }
  44. { procedure second_class_to_intf;override; }
  45. { procedure second_char_to_char;override; }
  46. {$ifdef TESTOBJEXT2}
  47. procedure checkobject;override;
  48. {$endif TESTOBJEXT2}
  49. end;
  50. implementation
  51. uses
  52. verbose,systems,
  53. symconst,symdef,aasmbase,aasmtai,aasmcpu,
  54. cgbase,
  55. ncon,ncal,ncnv,
  56. cpubase,
  57. cgobj,cga,cgx86;
  58. function ti386typeconvnode.first_int_to_real : tnode;
  59. begin
  60. first_int_to_real:=nil;
  61. if registersfpu<1 then
  62. registersfpu:=1;
  63. expectloc:=LOC_FPUREGISTER;
  64. end;
  65. procedure ti386typeconvnode.second_int_to_real;
  66. var
  67. href : treference;
  68. hregister : tregister;
  69. l1,l2 : tasmlabel;
  70. freereg : boolean;
  71. begin
  72. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  73. hregister:=NR_NO;
  74. freereg:=false;
  75. { for u32bit a solution is to push $0 and to load a comp }
  76. { does this first, it destroys maybe EDI }
  77. if torddef(left.resulttype.def).typ=u32bit then
  78. exprasmlist.concat(taicpu.op_const(A_PUSH,S_L,0));
  79. case left.location.loc of
  80. LOC_REGISTER,
  81. LOC_CREGISTER :
  82. begin
  83. case left.location.size of
  84. OS_64,OS_S64 :
  85. begin
  86. exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,left.location.registerhigh));
  87. hregister:=left.location.registerlow;
  88. end;
  89. OS_32,OS_S32 :
  90. hregister:=left.location.register;
  91. else
  92. begin
  93. hregister:=cg.getintregister(exprasmlist,OS_32);
  94. freereg:=true;
  95. cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hregister);
  96. end;
  97. end;
  98. end;
  99. LOC_REFERENCE,
  100. LOC_CREFERENCE :
  101. begin
  102. hregister:=cg.getintregister(exprasmlist,OS_INT);
  103. freereg:=true;
  104. if left.location.size in [OS_64,OS_S64] then
  105. begin
  106. href:=left.location.reference;
  107. inc(href.offset,4);
  108. cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,href,hregister);
  109. exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,hregister));
  110. cg.a_load_ref_reg(exprasmlist,OS_32,OS_32,left.location.reference,hregister);
  111. end
  112. else
  113. cg.a_load_ref_reg(exprasmlist,left.location.size,OS_INT,left.location.reference,hregister);
  114. end;
  115. else
  116. internalerror(2002032218);
  117. end;
  118. location_release(exprasmlist,left.location);
  119. location_freetemp(exprasmlist,left.location);
  120. { for 64 bit integers, the high dword is already pushed }
  121. exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,hregister));
  122. if freereg then
  123. cg.ungetregister(exprasmlist,hregister);
  124. reference_reset_base(href,NR_ESP,0);
  125. case torddef(left.resulttype.def).typ of
  126. u32bit:
  127. begin
  128. emit_ref(A_FILD,S_IQ,href);
  129. emit_const_reg(A_ADD,S_L,8,NR_ESP);
  130. end;
  131. scurrency,
  132. s64bit:
  133. begin
  134. emit_ref(A_FILD,S_IQ,href);
  135. emit_const_reg(A_ADD,S_L,8,NR_ESP);
  136. end;
  137. u64bit:
  138. begin
  139. { unsigned 64 bit ints are harder to handle: }
  140. { we load bits 0..62 and then check bit 63: }
  141. { if it is 1 then we add $80000000 000000000 }
  142. { as double }
  143. inc(href.offset,4);
  144. hregister:=cg.getintregister(exprasmlist,OS_32);
  145. cg.a_load_ref_reg(exprasmlist,OS_INT,OS_INT,href,hregister);
  146. reference_reset_base(href,NR_ESP,4);
  147. emit_const_ref(A_AND,S_L,$7fffffff,href);
  148. emit_const_reg(A_TEST,S_L,longint($80000000),hregister);
  149. cg.ungetregister(exprasmlist,hregister);
  150. reference_reset_base(href,NR_ESP,0);
  151. emit_ref(A_FILD,S_IQ,href);
  152. objectlibrary.getdatalabel(l1);
  153. objectlibrary.getlabel(l2);
  154. cg.a_jmp_flags(exprasmlist,F_E,l2);
  155. Consts.concat(Tai_label.Create(l1));
  156. { I got this constant from a test progtram (FK) }
  157. Consts.concat(Tai_const.Create_32bit(0));
  158. Consts.concat(Tai_const.Create_32bit(1138753536));
  159. reference_reset_symbol(href,l1,0);
  160. emit_ref(A_FADD,S_FL,href);
  161. cg.a_label(exprasmlist,l2);
  162. emit_const_reg(A_ADD,S_L,8,NR_ESP);
  163. end
  164. else
  165. begin
  166. emit_ref(A_FILD,S_IL,href);
  167. hregister:=cg.getintregister(exprasmlist,OS_32);
  168. emit_reg(A_POP,S_L,hregister);
  169. cg.ungetregister(exprasmlist,hregister);
  170. end;
  171. end;
  172. tcgx86(cg).inc_fpu_stack;
  173. location.register:=NR_ST;
  174. end;
  175. {$ifdef TESTOBJEXT2}
  176. procedure ti386typeconvnode.checkobject;
  177. var
  178. r : preference;
  179. nillabel : plabel;
  180. begin
  181. new(r);
  182. reset_reference(r^);
  183. if p^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  184. r^.base:=p^.location.register
  185. else
  186. begin
  187. cg.getexplicitregister(exprasmlist,R_EDI);
  188. emit_mov_loc_reg(p^.location,R_EDI);
  189. r^.base:=R_EDI;
  190. end;
  191. { NIL must be accepted !! }
  192. emit_reg_reg(A_OR,S_L,r^.base,r^.base);
  193. rg.ungetregisterint(exprasmlist,R_EDI);
  194. objectlibrary.getlabel(nillabel);
  195. cg.a_jmp_flags(exprasmlist,F_E,nillabel);
  196. { this is one point where we need vmt_offset (PM) }
  197. r^.offset:= tobjectdef(tpointerdef(p^.resulttype.def).definition).vmt_offset;
  198. rg.getexplicitregisterint(exprasmlist,R_EDI);
  199. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  200. emit_sym(A_PUSH,S_L,
  201. objectlibrary.newasmsymbol(tobjectdef(tpointerdef(p^.resulttype.def).definition).vmt_mangledname));
  202. emit_reg(A_PUSH,S_L,R_EDI);
  203. rg.ungetregister32(exprasmlist,R_EDI);
  204. emitcall('FPC_CHECK_OBJECT_EXT');
  205. emitlab(nillabel);
  206. end;
  207. {$endif TESTOBJEXT2}
  208. begin
  209. ctypeconvnode:=ti386typeconvnode;
  210. end.
  211. {
  212. $Log$
  213. Revision 1.68 2003-11-04 22:30:15 florian
  214. + type cast variant<->enum
  215. * cnv. node second pass uses now as well helper wrappers
  216. Revision 1.67 2003/10/10 17:48:14 peter
  217. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  218. * tregisteralloctor renamed to trgobj
  219. * removed rgobj from a lot of units
  220. * moved location_* and reference_* to cgobj
  221. * first things for mmx register allocation
  222. Revision 1.66 2003/10/09 21:31:37 daniel
  223. * Register allocator splitted, ans abstract now
  224. Revision 1.65 2003/10/01 20:34:49 peter
  225. * procinfo unit contains tprocinfo
  226. * cginfo renamed to cgbase
  227. * moved cgmessage to verbose
  228. * fixed ppc and sparc compiles
  229. Revision 1.64 2003/09/28 21:48:20 peter
  230. * fix register leaks
  231. Revision 1.63 2003/09/03 15:55:01 peter
  232. * NEWRA branch merged
  233. Revision 1.62.2.2 2003/08/31 15:46:26 peter
  234. * more updates for tregister
  235. Revision 1.62.2.1 2003/08/31 13:58:46 daniel
  236. * Some more work to make things compile
  237. Revision 1.62 2003/06/03 21:11:09 peter
  238. * cg.a_load_* get a from and to size specifier
  239. * makeregsize only accepts newregister
  240. * i386 uses generic tcgnotnode,tcgunaryminus
  241. Revision 1.61 2003/04/30 20:53:32 florian
  242. * error when address of an abstract method is taken
  243. * fixed some x86-64 problems
  244. * merged some more x86-64 and i386 code
  245. Revision 1.60 2003/04/23 20:16:04 peter
  246. + added currency support based on int64
  247. + is_64bit for use in cg units instead of is_64bitint
  248. * removed cgmessage from n386add, replace with internalerrors
  249. Revision 1.59 2003/04/22 23:50:23 peter
  250. * firstpass uses expectloc
  251. * checks if there are differences between the expectloc and
  252. location.loc from secondpass in EXTDEBUG
  253. Revision 1.58 2003/04/22 10:09:35 daniel
  254. + Implemented the actual register allocator
  255. + Scratch registers unavailable when new register allocator used
  256. + maybe_save/maybe_restore unavailable when new register allocator used
  257. Revision 1.57 2003/03/13 19:52:23 jonas
  258. * and more new register allocator fixes (in the i386 code generator this
  259. time). At least now the ppc cross compiler can compile the linux
  260. system unit again, but I haven't tested it.
  261. Revision 1.56 2003/02/19 22:00:15 daniel
  262. * Code generator converted to new register notation
  263. - Horribily outdated todo.txt removed
  264. Revision 1.55 2003/01/13 18:37:44 daniel
  265. * Work on register conversion
  266. Revision 1.54 2003/01/08 18:43:57 daniel
  267. * Tregister changed into a record
  268. Revision 1.53 2002/12/05 14:27:42 florian
  269. * some variant <-> dyn. array stuff
  270. Revision 1.52 2002/11/25 17:43:26 peter
  271. * splitted defbase in defutil,symutil,defcmp
  272. * merged isconvertable and is_equal into compare_defs(_ext)
  273. * made operator search faster by walking the list only once
  274. Revision 1.51 2002/10/10 16:14:54 florian
  275. * fixed to reflect last tconvtype change
  276. Revision 1.50 2002/10/05 12:43:29 carl
  277. * fixes for Delphi 6 compilation
  278. (warning : Some features do not work under Delphi)
  279. Revision 1.49 2002/09/17 18:54:03 jonas
  280. * a_load_reg_reg() now has two size parameters: source and dest. This
  281. allows some optimizations on architectures that don't encode the
  282. register size in the register name.
  283. Revision 1.48 2002/08/14 19:19:14 carl
  284. * first_int_to_real moved to i386 (other one is generic)
  285. Revision 1.47 2002/08/11 14:32:30 peter
  286. * renamed current_library to objectlibrary
  287. Revision 1.46 2002/08/11 13:24:16 peter
  288. * saving of asmsymbols in ppu supported
  289. * asmsymbollist global is removed and moved into a new class
  290. tasmlibrarydata that will hold the info of a .a file which
  291. corresponds with a single module. Added librarydata to tmodule
  292. to keep the library info stored for the module. In the future the
  293. objectfiles will also be stored to the tasmlibrarydata class
  294. * all getlabel/newasmsymbol and friends are moved to the new class
  295. Revision 1.45 2002/07/27 19:53:51 jonas
  296. + generic implementation of tcg.g_flags2ref()
  297. * tcg.flags2xxx() now also needs a size parameter
  298. Revision 1.44 2002/07/20 11:58:01 florian
  299. * types.pas renamed to defbase.pas because D6 contains a types
  300. unit so this would conflicts if D6 programms are compiled
  301. + Willamette/SSE2 instructions to assembler added
  302. Revision 1.43 2002/07/01 18:46:31 peter
  303. * internal linker
  304. * reorganized aasm layer
  305. Revision 1.42 2002/05/20 13:30:40 carl
  306. * bugfix of hdisponen (base must be set, not index)
  307. * more portability fixes
  308. Revision 1.41 2002/05/18 13:34:24 peter
  309. * readded missing revisions
  310. Revision 1.40 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.38 2002/05/12 16:53:17 peter
  316. * moved entry and exitcode to ncgutil and cgobj
  317. * foreach gets extra argument for passing local data to the
  318. iterator function
  319. * -CR checks also class typecasts at runtime by changing them
  320. into as
  321. * fixed compiler to cycle with the -CR option
  322. * fixed stabs with elf writer, finally the global variables can
  323. be watched
  324. * removed a lot of routines from cga unit and replaced them by
  325. calls to cgobj
  326. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  327. u32bit then the other is typecasted also to u32bit without giving
  328. a rangecheck warning/error.
  329. * fixed pascal calling method with reversing also the high tree in
  330. the parast, detected by tcalcst3 test
  331. Revision 1.37 2002/04/21 19:02:07 peter
  332. * removed newn and disposen nodes, the code is now directly
  333. inlined from pexpr
  334. * -an option that will write the secondpass nodes to the .s file, this
  335. requires EXTDEBUG define to actually write the info
  336. * fixed various internal errors and crashes due recent code changes
  337. Revision 1.36 2002/04/21 15:35:23 carl
  338. * changeregsize -> rg.makeregsize
  339. Revision 1.35 2002/04/19 15:39:35 peter
  340. * removed some more routines from cga
  341. * moved location_force_reg/mem to ncgutil
  342. * moved arrayconstructnode secondpass to ncgld
  343. Revision 1.34 2002/04/15 19:44:21 peter
  344. * fixed stackcheck that would be called recursively when a stack
  345. error was found
  346. * generic changeregsize(reg,size) for i386 register resizing
  347. * removed some more routines from cga unit
  348. * fixed returnvalue handling
  349. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  350. Revision 1.33 2002/04/04 19:06:10 peter
  351. * removed unused units
  352. * use tlocation.size in cg.a_*loc*() routines
  353. Revision 1.32 2002/04/02 17:11:36 peter
  354. * tlocation,treference update
  355. * LOC_CONSTANT added for better constant handling
  356. * secondadd splitted in multiple routines
  357. * location_force_reg added for loading a location to a register
  358. of a specified size
  359. * secondassignment parses now first the right and then the left node
  360. (this is compatible with Kylix). This saves a lot of push/pop especially
  361. with string operations
  362. * adapted some routines to use the new cg methods
  363. Revision 1.31 2002/03/31 20:26:38 jonas
  364. + a_loadfpu_* and a_loadmm_* methods in tcg
  365. * register allocation is now handled by a class and is mostly processor
  366. independent (+rgobj.pas and i386/rgcpu.pas)
  367. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  368. * some small improvements and fixes to the optimizer
  369. * some register allocation fixes
  370. * some fpuvaroffset fixes in the unary minus node
  371. * push/popusedregisters is now called rg.save/restoreusedregisters and
  372. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  373. also better optimizable)
  374. * fixed and optimized register saving/restoring for new/dispose nodes
  375. * LOC_FPU locations now also require their "register" field to be set to
  376. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  377. - list field removed of the tnode class because it's not used currently
  378. and can cause hard-to-find bugs
  379. Revision 1.30 2002/03/04 19:10:13 peter
  380. * removed compiler warnings
  381. }