cpubase.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
  4. Contains the basic declarations for the x86-64 architecture
  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. { This unit contains the basic declarations for the x86-64 architecture.
  19. }
  20. unit cpubase;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globals,cutils,cclasses,
  25. aasmbase,
  26. cpuinfo,
  27. cginfo;
  28. {*****************************************************************************
  29. Assembler Opcodes
  30. *****************************************************************************}
  31. type
  32. TAsmOp={$i x86_64op.inc}
  33. { This should define the array of instructions as string }
  34. op2strtable=array[tasmop] of string[11];
  35. Const
  36. { First value of opcode enumeration }
  37. firstop = low(tasmop);
  38. { Last value of opcode enumeration }
  39. lastop = high(tasmop);
  40. {*****************************************************************************
  41. Operand Sizes
  42. *****************************************************************************}
  43. type
  44. topsize = (S_NO,
  45. S_B,S_W,S_L,S_BW,S_BL,S_WL,S_BQ,S_WQ,S_LQ,
  46. S_IS,S_IL,S_IQ,
  47. S_FS,S_FL,S_FX,S_D,S_Q,S_FV,
  48. S_NEAR,S_FAR,S_SHORT
  49. );
  50. {*****************************************************************************
  51. Registers
  52. *****************************************************************************}
  53. type
  54. { don't change the order }
  55. { it's used by the register size conversions }
  56. { Enumeration of all registers of the CPU }
  57. tregister = (R_NO,
  58. R_RAX,R_RCX,R_RDX,R_RBX,R_RSP,R_RBP,R_RSI,R_RDI,
  59. R_R8,R_R9,R_R10,R_R11,R_R12,R_R13,R_R14,R_R15,R_RIP,
  60. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  61. R_R8D,R_R9D,R_R10D,R_R11D,R_R12D,R_R13D,R_R14D,R_R15D,
  62. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  63. R_R8W,R_R9W,R_R10W,R_R11W,R_R12W,R_R13W,R_R14W,R_R15W,
  64. R_AL,R_CL,R_DL,R_BL,R_SPL,R_BPL,R_SIL,R_DIL,
  65. R_R8B,R_R9B,R_R10B,R_R11B,R_R12B,R_R13B,R_R14B,R_R15B,
  66. 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. R_XMM8,R_XMM9,R_XMM10,R_XMM11,R_XMM12,R_XMM13,R_XMM14,R_XMM15
  75. );
  76. { A type to store register locations for 64 Bit values. }
  77. tregister64 = tregister;
  78. { alias for compact code }
  79. treg64 = tregister64;
  80. { Set type definition for registers }
  81. tregisterset = set of tregister;
  82. { Type definition for the array of string of register names }
  83. reg2strtable = array[tregister] of string[6];
  84. const
  85. firstreg = low(tregister);
  86. lastreg = high(tregister);
  87. firstsreg = R_CS;
  88. lastsreg = R_GS;
  89. regset8bit : tregisterset = [R_AL..R_DH];
  90. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  91. regset32bit : tregisterset = [R_EAX..R_EDI];
  92. { Convert reg to opsize }
  93. reg2opsize:array[firstreg..lastreg] of topsize = (S_NO,
  94. S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,
  95. S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,S_Q,
  96. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  97. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  98. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  99. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  100. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  101. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  102. S_B,S_B,S_B,S_B,
  103. S_W,S_W,S_W,S_W,S_W,S_W,
  104. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  105. S_L,S_L,S_L,S_L,S_L,S_L,
  106. S_L,S_L,S_L,S_L,
  107. S_L,S_L,S_L,S_L,S_L,
  108. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  109. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  110. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  111. );
  112. { Standard opcode string table (for each tasmop enumeration). The
  113. opcode strings should conform to the names as defined by the
  114. processor manufacturer.
  115. }
  116. std_op2str:op2strtable={$i x86_64in.inc}
  117. { Standard register table (for each tregister enumeration). The
  118. register strings should conform to the the names as defined
  119. by the processor manufacturer
  120. }
  121. std_reg2str : reg2strtable = ('',
  122. 'rax','rcx','rdx','rbx','rsp','rbp','rsi','rdi',
  123. 'r8','r9','r10','r11','r12','r13','r14','r15','rip',
  124. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  125. 'r8d','r9d','r10d','r11d','r12d','r13d','r14d','r15d',
  126. 'ax','cx','dx','bx','sp','bp','si','di',
  127. 'r8w','r9w','r10w','r11w','r12w','r13w','r14w','r15w',
  128. 'al','cl','dl','bl','spl','bpl','sil','dil',
  129. 'r8b','r9b','r10b','r11b','r12b','r13b','r14b','r15b',
  130. 'ah','ch','bh','dh',
  131. 'cs','ds','es','ss','fs','gs',
  132. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  133. 'dr0','dr1','dr2','dr3','dr6','dr7',
  134. 'cr0','cr2','cr3','cr4',
  135. 'tr3','tr4','tr5','tr6','tr7',
  136. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  137. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7',
  138. 'xmm8','xmm9','xmm10','xmm11','xmm12','xmm13','xmm14','xmm15');
  139. {*****************************************************************************
  140. Conditions
  141. *****************************************************************************}
  142. type
  143. TAsmCond=(C_None,
  144. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  145. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  146. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  147. );
  148. const
  149. cond2str:array[TAsmCond] of string[3]=('',
  150. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  151. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  152. 'ns','nz','o','p','pe','po','s','z'
  153. );
  154. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  155. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  156. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  157. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  158. );
  159. {*****************************************************************************
  160. Flags
  161. *****************************************************************************}
  162. type
  163. 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);
  164. {*****************************************************************************
  165. Reference
  166. *****************************************************************************}
  167. type
  168. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  169. { immediate/reference record }
  170. preference = ^treference;
  171. treference = packed record
  172. offset : longint;
  173. symbol : tasmsymbol;
  174. offsetfixup : longint;
  175. segment,
  176. base,
  177. index : tregister;
  178. scalefactor : byte;
  179. options : trefoptions;
  180. alignment : byte;
  181. end;
  182. { reference record }
  183. pparareference = ^tparareference;
  184. tparareference = packed record
  185. index : tregister;
  186. offset : longint;
  187. end;
  188. {*****************************************************************************
  189. Operands
  190. *****************************************************************************}
  191. { Types of operand }
  192. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  193. toper=record
  194. ot : longint;
  195. case typ : toptype of
  196. top_none : ();
  197. top_reg : (reg:tregister);
  198. top_ref : (ref:preference);
  199. top_const : (val:longint);
  200. top_symbol : (sym:tasmsymbol;symofs:longint);
  201. end;
  202. {*****************************************************************************
  203. Generic Location
  204. *****************************************************************************}
  205. type
  206. TLoc=(
  207. { added for tracking problems}
  208. LOC_INVALID,
  209. { contant }
  210. LOC_CONSTANT,
  211. { in a processor register }
  212. LOC_REGISTER,
  213. { in memory }
  214. LOC_CREFERENCE,
  215. { like LOC_MEM, but lvalue }
  216. LOC_REFERENCE,
  217. { boolean results only, jump to false or true label }
  218. LOC_JUMP,
  219. { boolean results only, flags are set }
  220. LOC_FLAGS,
  221. { Constant register which shouldn't be modified }
  222. LOC_CREGISTER,
  223. { MMX register }
  224. LOC_MMXREGISTER,
  225. { Constant MMX register }
  226. LOC_CMMXREGISTER,
  227. { FPU stack }
  228. LOC_FPUREGISTER,
  229. { if it is a FPU register variable on the fpu stack }
  230. LOC_CFPUREGISTER,
  231. LOC_SSEREGISTER,
  232. LOC_CSSEREGISTER
  233. );
  234. { tparamlocation describes where a parameter for a procedure is stored.
  235. References are given from the caller's point of view. The usual
  236. TLocation isn't used, because contains a lot of unnessary fields.
  237. }
  238. tparalocation = packed record
  239. loc : TLoc;
  240. sp_fixup : longint;
  241. case TLoc of
  242. LOC_REFERENCE : (reference : tparareference);
  243. { segment in reference at the same place as in loc_register }
  244. LOC_REGISTER,LOC_CREGISTER : (
  245. case longint of
  246. 1 : (register,registerhigh : tregister);
  247. { overlay a registerlow }
  248. 2 : (registerlow : tregister);
  249. { overlay a 64 Bit register type }
  250. 3 : (reg64 : tregister64);
  251. 4 : (register64 : tregister64);
  252. );
  253. { it's only for better handling }
  254. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  255. end;
  256. plocation = ^tlocation;
  257. tlocation = packed record
  258. loc : tloc;
  259. size : TCGSize;
  260. case TLoc of
  261. LOC_FLAGS : (resflags : tresflags);
  262. LOC_CONSTANT : (
  263. case longint of
  264. 1 : (value : AWord);
  265. 2 : (valuelow, valuehigh:AWord);
  266. { overlay a complete 64 Bit value }
  267. 3 : (valueqword : qword);
  268. );
  269. LOC_CREFERENCE,LOC_REFERENCE : (reference : treference);
  270. { segment in reference at the same place as in loc_register }
  271. LOC_REGISTER,LOC_CREGISTER : (
  272. case longint of
  273. 1 : (register,segment,registerhigh : tregister);
  274. { overlay a registerlow }
  275. 2 : (registerlow : tregister);
  276. { overlay a 64 Bit register type }
  277. 3 : (reg64 : tregister64);
  278. 4 : (register64 : tregister64);
  279. );
  280. { it's only for better handling }
  281. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  282. end;
  283. {*****************************************************************************
  284. Constants
  285. *****************************************************************************}
  286. const
  287. max_operands = 3;
  288. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  289. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  290. ALL_REGISTERS = [R_EAX..R_XMM15];
  291. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  292. { low and high of the available maximum width integer general purpose }
  293. { registers }
  294. LoGPReg = R_EAX;
  295. HiGPReg = R_EDI;
  296. { low and high of every possible width general purpose register (same as }
  297. { above on most architctures apart from the 80x86) }
  298. LoReg = R_EAX;
  299. HiReg = R_BL;
  300. intregs = general_registers;
  301. maxvarregs = 4;
  302. varregs : array[1..maxvarregs] of tregister =
  303. (R_EBX,R_EDX,R_ECX,R_EAX);
  304. usableregsint = [R_EAX,R_EBX,R_ECX,R_EDX];
  305. c_countusableregsint = 4;
  306. maxfpuvarregs = 16;
  307. maxintregs = maxvarregs;
  308. maxfpuregs = maxfpuvarregs;
  309. fpuregs = [R_ST0..R_ST7];
  310. usableregsfpu = [];
  311. c_countusableregsfpu = 0;
  312. mmregs = [R_MM0..R_MM7];
  313. usableregsmm = [R_XMM0..R_XMM15];
  314. c_countusableregsmm = 8;
  315. firstsaveintreg = R_EAX;
  316. lastsaveintreg = R_R15;
  317. firstsavefpureg = R_NO;
  318. lastsavefpureg = R_NO;
  319. firstsavemmreg = R_XMM0;
  320. lastsavemmreg = R_XMM15;
  321. registers_saved_on_cdecl = [R_ESI,R_EDI,R_EBX];
  322. scratch_regs : array[1..1] of tregister = (R_EDI);
  323. {*****************************************************************************
  324. Default generic sizes
  325. *****************************************************************************}
  326. { Defines the default address size for a processor, }
  327. OS_ADDR = OS_32;
  328. { the natural int size for a processor, }
  329. OS_INT = OS_32;
  330. { the maximum float size for a processor, }
  331. OS_FLOAT = OS_F80;
  332. { the size of a vector register for a processor }
  333. OS_VECTOR = OS_M64;
  334. cpuflags = [];
  335. { sizes }
  336. pointersize = 8;
  337. extended_size = 10;
  338. sizepostfix_pointer = S_L;
  339. {*****************************************************************************
  340. Generic Register names
  341. *****************************************************************************}
  342. { location of function results }
  343. stack_pointer_reg = R_RSP;
  344. frame_pointer_reg = R_RBP;
  345. self_pointer_reg = R_RSI;
  346. accumulator = R_RAX;
  347. {the return_result_reg, is used inside the called function to store its return
  348. value when that is a scalar value otherwise a pointer to the address of the
  349. result is placed inside it}
  350. return_result_reg = accmulator;
  351. {the function_result_reg contains the function result after a call to a scalar
  352. function othewise it contains a pointer to the returned result}
  353. function_result_reg = accumulator;
  354. accumulatorhigh = R_RDX;
  355. { the register where the vmt offset is passed to the destructor }
  356. { helper routine }
  357. vmt_offset_reg = R_RDI;
  358. resultreg = R_RAX;
  359. resultreg64 = R_RAX;
  360. fpu_result_reg = R_ST;
  361. {*****************************************************************************
  362. GCC /ABI linking information
  363. *****************************************************************************}
  364. const
  365. { Registers which must be saved when calling a routine declared as
  366. cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
  367. saved should be the ones as defined in the target ABI and / or GCC.
  368. This value can be deduced from the CALLED_USED_REGISTERS array in the
  369. GCC source.
  370. }
  371. std_saved_registers = [R_ESI,R_EDI,R_EBX];
  372. { Required parameter alignment when calling a routine declared as
  373. stdcall and cdecl. The alignment value should be the one defined
  374. by GCC or the target ABI.
  375. The value of this constant is equal to the constant
  376. PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
  377. }
  378. std_param_align = 8;
  379. {*****************************************************************************
  380. Helpers
  381. *****************************************************************************}
  382. function is_calljmp(o:tasmop):boolean;
  383. function flags_to_cond(const f: TResFlags) : TAsmCond;
  384. implementation
  385. {*****************************************************************************
  386. Helpers
  387. *****************************************************************************}
  388. function is_calljmp(o:tasmop):boolean;
  389. begin
  390. case o of
  391. A_CALL,
  392. A_JCXZ,
  393. A_JECXZ,
  394. A_JMP,
  395. A_LOOP,
  396. A_LOOPE,
  397. A_LOOPNE,
  398. A_LOOPNZ,
  399. A_LOOPZ,
  400. A_Jcc :
  401. is_calljmp:=true;
  402. else
  403. is_calljmp:=false;
  404. end;
  405. end;
  406. function flags_to_cond(const f: TResFlags) : TAsmCond;
  407. const
  408. flags_2_cond : array[TResFlags] of TAsmCond =
  409. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  410. begin
  411. result := flags_2_cond[f];
  412. end;
  413. end.
  414. {
  415. $Log$
  416. Revision 1.3 2002-11-17 17:49:09 mazen
  417. + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
  418. Revision 1.2 2002/07/25 22:55:33 florian
  419. * several fixes, small test units can be compiled
  420. Revision 1.1 2002/07/24 22:38:15 florian
  421. + initial release of x86-64 target code
  422. }