n386cnv.pas 14 KB

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