cpubase.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  4. Contains the base types for the i386
  5. * This code was inspired by the NASM sources
  6. The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. {# Base unit for processor information. This unit contains
  22. enumerations of registers, opcodes, sizes, and other
  23. such things which are processor specific.
  24. }
  25. unit cpubase;
  26. {$i fpcdefs.inc}
  27. interface
  28. uses
  29. globals,cutils,cclasses,aasm,cpuinfo,cginfo;
  30. {*****************************************************************************
  31. Assembler Opcodes
  32. *****************************************************************************}
  33. type
  34. TAsmOp={$i i386op.inc}
  35. {# This should define the array of instructions as string }
  36. op2strtable=array[tasmop] of string[11];
  37. Const
  38. {# First value of opcode enumeration }
  39. firstop = low(tasmop);
  40. {# Last value of opcode enumeration }
  41. lastop = high(tasmop);
  42. {*****************************************************************************
  43. Operand Sizes
  44. *****************************************************************************}
  45. type
  46. topsize = (S_NO,
  47. S_B,S_W,S_L,S_BW,S_BL,S_WL,
  48. S_IS,S_IL,S_IQ,
  49. S_FS,S_FL,S_FX,S_D,S_Q,S_FV,
  50. S_NEAR,S_FAR,S_SHORT
  51. );
  52. {*****************************************************************************
  53. Registers
  54. *****************************************************************************}
  55. type
  56. {# Enumeration for all possible registers for cpu. It
  57. is to note that all registers of the same type
  58. (for example all FPU registers), should be grouped
  59. together.
  60. }
  61. { don't change the order }
  62. { it's used by the register size conversions }
  63. tregister = (R_NO,
  64. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  65. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  66. R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_BH,R_DH,
  67. R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
  68. R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
  69. R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
  70. R_CR0,R_CR2,R_CR3,R_CR4,
  71. R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
  72. R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
  73. R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7
  74. );
  75. {# Set type definition for registers }
  76. tregisterset = set of tregister;
  77. {# Type definition for the array of string of register nnames }
  78. reg2strtable = array[tregister] of string[6];
  79. const
  80. {# First register in the tregister enumeration }
  81. firstreg = low(tregister);
  82. {# Last register in the tregister enumeration }
  83. lastreg = high(tregister);
  84. firstsreg = R_CS;
  85. lastsreg = R_GS;
  86. regset8bit : tregisterset = [R_AL..R_DH];
  87. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  88. regset32bit : tregisterset = [R_EAX..R_EDI];
  89. { Convert reg to opsize }
  90. reg2opsize : array[firstreg..lastreg] of topsize = (S_NO,
  91. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  92. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  93. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  94. S_W,S_W,S_W,S_W,S_W,S_W,
  95. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  96. S_L,S_L,S_L,S_L,S_L,S_L,
  97. S_L,S_L,S_L,S_L,
  98. S_L,S_L,S_L,S_L,S_L,
  99. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  100. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  101. );
  102. {# Standard opcode string table (for each tasmop enumeration). The
  103. opcode strings should conform to the names as defined by the
  104. processor manufacturer.
  105. }
  106. std_op2str:op2strtable={$i i386int.inc}
  107. {# Standard register table (for each tregister enumeration). The
  108. register strings should conform to the the names as defined
  109. by the processor manufacturer
  110. }
  111. std_reg2str : reg2strtable = ('',
  112. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  113. 'ax','cx','dx','bx','sp','bp','si','di',
  114. 'al','cl','dl','bl','ah','ch','bh','dh',
  115. 'cs','ds','es','ss','fs','gs',
  116. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  117. 'dr0','dr1','dr2','dr3','dr6','dr7',
  118. 'cr0','cr2','cr3','cr4',
  119. 'tr3','tr4','tr5','tr6','tr7',
  120. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  121. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  122. );
  123. {*****************************************************************************
  124. Conditions
  125. *****************************************************************************}
  126. type
  127. TAsmCond=(C_None,
  128. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  129. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  130. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  131. );
  132. const
  133. cond2str:array[TAsmCond] of string[3]=('',
  134. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  135. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  136. 'ns','nz','o','p','pe','po','s','z'
  137. );
  138. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  139. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  140. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  141. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  142. );
  143. {*****************************************************************************
  144. Flags
  145. *****************************************************************************}
  146. type
  147. TResFlags = (F_E,F_NE,F_G,F_L,F_GE,F_LE,F_C,F_NC,F_A,F_AE,F_B,F_BE);
  148. {*****************************************************************************
  149. Reference
  150. *****************************************************************************}
  151. type
  152. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  153. { reference record }
  154. preference = ^treference;
  155. treference = packed record
  156. segment,
  157. base,
  158. index : tregister;
  159. scalefactor : byte;
  160. offset : longint;
  161. symbol : tasmsymbol;
  162. offsetfixup : longint;
  163. options : trefoptions;
  164. end;
  165. {*****************************************************************************
  166. Operands
  167. *****************************************************************************}
  168. { Types of operand }
  169. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  170. toper=record
  171. ot : longint;
  172. case typ : toptype of
  173. top_none : ();
  174. top_reg : (reg:tregister);
  175. top_ref : (ref:preference);
  176. top_const : (val:aword);
  177. top_symbol : (sym:tasmsymbol;symofs:longint);
  178. end;
  179. {*****************************************************************************
  180. Generic Location
  181. *****************************************************************************}
  182. type
  183. TLoc=(
  184. LOC_INVALID, { added for tracking problems}
  185. LOC_CONSTANT, { constant value }
  186. LOC_JUMP, { boolean results only, jump to false or true label }
  187. LOC_FLAGS, { boolean results only, flags are set }
  188. LOC_CREFERENCE, { in memory constant value reference (cannot change) }
  189. LOC_REFERENCE, { in memory value }
  190. LOC_REGISTER, { in a processor register }
  191. LOC_CREGISTER, { Constant register which shouldn't be modified }
  192. LOC_FPUREGISTER, { FPU stack }
  193. LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
  194. LOC_MMXREGISTER, { MMX register }
  195. LOC_CMMXREGISTER, { MMX register variable }
  196. LOC_SSEREGISTER,
  197. LOC_CSSEREGISTER
  198. );
  199. tlocation = packed record
  200. loc : TLoc;
  201. size : TCGSize;
  202. case TLoc of
  203. LOC_FLAGS : (resflags : tresflags);
  204. LOC_CONSTANT : (
  205. case longint of
  206. 1 : (value : AWord);
  207. 2 : (valuelow, valuehigh:AWord);
  208. );
  209. LOC_CREFERENCE,
  210. LOC_REFERENCE : (reference : treference);
  211. { segment in reference at the same place as in loc_register }
  212. LOC_REGISTER,LOC_CREGISTER : (
  213. case longint of
  214. 1 : (register,segment,registerhigh : tregister);
  215. { overlay a registerlow }
  216. 2 : (registerlow : tregister);
  217. );
  218. { it's only for better handling }
  219. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  220. end;
  221. {*****************************************************************************
  222. Constants
  223. *****************************************************************************}
  224. const
  225. max_operands = 3;
  226. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  227. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  228. {# Constant defining possibly all registers which might require saving }
  229. ALL_REGISTERS = [firstreg..lastreg];
  230. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  231. {# low and high of the available maximum width integer general purpose }
  232. { registers }
  233. LoGPReg = R_EAX;
  234. HiGPReg = R_EDX;
  235. {# low and high of every possible width general purpose register (same as }
  236. { above on most architctures apart from the 80x86) }
  237. LoReg = R_EAX;
  238. HiReg = R_DH;
  239. {# Table of registers which can be allocated by the code generator
  240. internally, when generating the code.
  241. }
  242. { legend: }
  243. { xxxregs = set of all possibly used registers of that type in the code }
  244. { generator }
  245. { usableregsxxx = set of all 32bit components of registers that can be }
  246. { possible allocated to a regvar or using getregisterxxx (this }
  247. { excludes registers which can be only used for parameter }
  248. { passing on ABI's that define this) }
  249. { c_countusableregsxxx = amount of registers in the usableregsxxx set }
  250. maxintregs = 4;
  251. intregs = [R_EAX..R_BL];
  252. usableregsint = [R_EAX,R_EBX,R_ECX,R_EDX];
  253. c_countusableregsint = 4;
  254. maxfpuregs = 8;
  255. fpuregs = [R_ST0..R_ST7];
  256. usableregsfpu = [];
  257. c_countusableregsfpu = 0;
  258. mmregs = [R_MM0..R_MM7];
  259. usableregsmm = [R_MM0..R_MM7];
  260. c_countusableregsmm = 8;
  261. firstsaveintreg = R_EAX;
  262. lastsaveintreg = R_EBX;
  263. firstsavefpureg = R_NO;
  264. lastsavefpureg = R_NO;
  265. firstsavemmreg = R_MM0;
  266. lastsavemmreg = R_MM7;
  267. maxvarregs = 4;
  268. varregs : array[1..maxvarregs] of tregister =
  269. (R_EBX,R_EDX,R_ECX,R_EAX);
  270. maxfpuvarregs = 8;
  271. {# Registers which are defined as scratch and no need to save across
  272. routine calls or in assembler blocks.
  273. }
  274. max_scratch_regs = 1;
  275. scratch_regs : array[1..max_scratch_regs] of tregister = (R_EDI);
  276. {*****************************************************************************
  277. Default generic sizes
  278. *****************************************************************************}
  279. {# Defines the default address size for a processor, }
  280. OS_ADDR = OS_32;
  281. {# the natural int size for a processor, }
  282. OS_INT = OS_32;
  283. {# the maximum float size for a processor, }
  284. OS_FLOAT = OS_F80;
  285. {# the size of a vector register for a processor }
  286. OS_VECTOR = OS_M64;
  287. {*****************************************************************************
  288. Generic Register names
  289. *****************************************************************************}
  290. {# Stack pointer register }
  291. stack_pointer_reg = R_ESP;
  292. {# Frame pointer register }
  293. frame_pointer_reg = R_EBP;
  294. {# Self pointer register : contains the instance address of an
  295. object or class. }
  296. self_pointer_reg = R_ESI;
  297. {# Register for addressing absolute data in a position independant way,
  298. such as in PIC code. The exact meaning is ABI specific }
  299. pic_offset_reg = R_EBX;
  300. {# Results are returned in this register (32-bit values) }
  301. accumulator = R_EAX;
  302. {# Hi-Results are returned in this register (64-bit value high register) }
  303. accumulatorhigh = R_EDX;
  304. { WARNING: don't change to R_ST0!! See comments above implementation of }
  305. { a_loadfpu* methods in rgcpu (JM) }
  306. fpuresultreg = R_ST;
  307. mmresultreg = R_MM0;
  308. {*****************************************************************************
  309. GCC /ABI linking information
  310. *****************************************************************************}
  311. const
  312. {# Registers which must be saved when calling a routine declared as
  313. cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
  314. saved should be the ones as defined in the target ABI and / or GCC.
  315. This value can be deduced from the CALLED_USED_REGISTERS array in the
  316. GCC source.
  317. }
  318. std_saved_registers = [R_ESI,R_EDI,R_EBX];
  319. {# Required parameter alignment when calling a routine declared as
  320. stdcall and cdecl. The alignment value should be the one defined
  321. by GCC or the target ABI.
  322. The value of this constant is equal to the constant
  323. PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
  324. }
  325. std_param_align = 4;
  326. {*****************************************************************************
  327. CPU Dependent Constants
  328. *****************************************************************************}
  329. {*****************************************************************************
  330. Helpers
  331. *****************************************************************************}
  332. function is_calljmp(o:tasmop):boolean;
  333. function flags_to_cond(const f: TResFlags) : TAsmCond;
  334. implementation
  335. {*****************************************************************************
  336. Helpers
  337. *****************************************************************************}
  338. function is_calljmp(o:tasmop):boolean;
  339. begin
  340. case o of
  341. A_CALL,
  342. A_JCXZ,
  343. A_JECXZ,
  344. A_JMP,
  345. A_LOOP,
  346. A_LOOPE,
  347. A_LOOPNE,
  348. A_LOOPNZ,
  349. A_LOOPZ,
  350. A_Jcc :
  351. is_calljmp:=true;
  352. else
  353. is_calljmp:=false;
  354. end;
  355. end;
  356. function flags_to_cond(const f: TResFlags) : TAsmCond;
  357. const
  358. flags_2_cond : array[TResFlags] of TAsmCond =
  359. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  360. begin
  361. result := flags_2_cond[f];
  362. end;
  363. end.
  364. {
  365. $Log$
  366. Revision 1.23 2002-05-18 13:34:22 peter
  367. * readded missing revisions
  368. Revision 1.22 2002/05/16 19:46:50 carl
  369. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  370. + try to fix temp allocation (still in ifdef)
  371. + generic constructor calls
  372. + start of tassembler / tmodulebase class cleanup
  373. Revision 1.19 2002/05/12 16:53:16 peter
  374. * moved entry and exitcode to ncgutil and cgobj
  375. * foreach gets extra argument for passing local data to the
  376. iterator function
  377. * -CR checks also class typecasts at runtime by changing them
  378. into as
  379. * fixed compiler to cycle with the -CR option
  380. * fixed stabs with elf writer, finally the global variables can
  381. be watched
  382. * removed a lot of routines from cga unit and replaced them by
  383. calls to cgobj
  384. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  385. u32bit then the other is typecasted also to u32bit without giving
  386. a rangecheck warning/error.
  387. * fixed pascal calling method with reversing also the high tree in
  388. the parast, detected by tcalcst3 test
  389. Revision 1.18 2002/04/21 15:31:40 carl
  390. - removed some other stuff to their units
  391. Revision 1.17 2002/04/20 21:37:07 carl
  392. + generic FPC_CHECKPOINTER
  393. + first parameter offset in stack now portable
  394. * rename some constants
  395. + move some cpu stuff to other units
  396. - remove unused constents
  397. * fix stacksize for some targets
  398. * fix generic size problems which depend now on EXTEND_SIZE constant
  399. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  400. Revision 1.16 2002/04/15 19:53:54 peter
  401. * fixed conflicts between the last 2 commits
  402. Revision 1.15 2002/04/15 19:44:20 peter
  403. * fixed stackcheck that would be called recursively when a stack
  404. error was found
  405. * generic changeregsize(reg,size) for i386 register resizing
  406. * removed some more routines from cga unit
  407. * fixed returnvalue handling
  408. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  409. Revision 1.14 2002/04/15 19:12:09 carl
  410. + target_info.size_of_pointer -> pointer_size
  411. + some cleanup of unused types/variables
  412. * move several constants from cpubase to their specific units
  413. (where they are used)
  414. + att_Reg2str -> gas_reg2str
  415. + int_reg2str -> std_reg2str
  416. Revision 1.13 2002/04/14 16:59:41 carl
  417. + att_reg2str -> gas_reg2str
  418. Revision 1.12 2002/04/02 17:11:34 peter
  419. * tlocation,treference update
  420. * LOC_CONSTANT added for better constant handling
  421. * secondadd splitted in multiple routines
  422. * location_force_reg added for loading a location to a register
  423. of a specified size
  424. * secondassignment parses now first the right and then the left node
  425. (this is compatible with Kylix). This saves a lot of push/pop especially
  426. with string operations
  427. * adapted some routines to use the new cg methods
  428. Revision 1.11 2002/03/31 20:26:37 jonas
  429. + a_loadfpu_* and a_loadmm_* methods in tcg
  430. * register allocation is now handled by a class and is mostly processor
  431. independent (+rgobj.pas and i386/rgcpu.pas)
  432. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  433. * some small improvements and fixes to the optimizer
  434. * some register allocation fixes
  435. * some fpuvaroffset fixes in the unary minus node
  436. * push/popusedregisters is now called rg.save/restoreusedregisters and
  437. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  438. also better optimizable)
  439. * fixed and optimized register saving/restoring for new/dispose nodes
  440. * LOC_FPU locations now also require their "register" field to be set to
  441. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  442. - list field removed of the tnode class because it's not used currently
  443. and can cause hard-to-find bugs
  444. Revision 1.10 2002/03/04 19:10:12 peter
  445. * removed compiler warnings
  446. }