cpubase.pas 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  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. cutils,cclasses,
  30. globtype,globals,
  31. cpuinfo,
  32. aasmbase,
  33. cginfo
  34. {$ifdef delphi}
  35. ,dmisc
  36. {$endif}
  37. ;
  38. {*****************************************************************************
  39. Assembler Opcodes
  40. *****************************************************************************}
  41. type
  42. TAsmOp={$i i386op.inc}
  43. {# This should define the array of instructions as string }
  44. op2strtable=array[tasmop] of string[11];
  45. Const
  46. {# First value of opcode enumeration }
  47. firstop = low(tasmop);
  48. {# Last value of opcode enumeration }
  49. lastop = high(tasmop);
  50. {*****************************************************************************
  51. Operand Sizes
  52. *****************************************************************************}
  53. type
  54. topsize = (S_NO,
  55. S_B,S_W,S_L,S_BW,S_BL,S_WL,
  56. S_IS,S_IL,S_IQ,
  57. S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX,
  58. S_NEAR,S_FAR,S_SHORT
  59. );
  60. {*****************************************************************************
  61. Registers
  62. *****************************************************************************}
  63. {The new register coding:
  64. For now we'll use this, when the old register coding is away, we
  65. can change this into a cardinal or something so the amount of
  66. possible registers increases.
  67. High byte: Register number
  68. Low byte: Subregister
  69. Example:
  70. $0100 AL
  71. $0101 AH
  72. $0102 AX
  73. $0103 EAX
  74. $0104 RAX
  75. $0201 BL
  76. $0203 EBX}
  77. {Super register numbers:}
  78. const RS_SPECIAL = $00; {Special register}
  79. RS_EAX = $01; {EAX}
  80. RS_EBX = $02; {EBX}
  81. RS_ECX = $03; {ECX}
  82. RS_EDX = $04; {EDX}
  83. RS_ESI = $05; {ESI}
  84. RS_EDI = $06; {EDI}
  85. RS_EBP = $07; {EBP}
  86. RS_ESP = $08; {ESP}
  87. RS_R8 = $09; {R8}
  88. RS_R9 = $0a; {R9}
  89. RS_R10 = $0b; {R10}
  90. RS_R11 = $0c; {R11}
  91. RS_R12 = $0d; {R12}
  92. RS_R13 = $0e; {R13}
  93. RS_R14 = $0f; {R14}
  94. RS_R15 = $10; {R15}
  95. {Number of first and last superregister.}
  96. first_supreg = $01;
  97. last_supreg = $10;
  98. {Number of first and last imaginary register.}
  99. first_imreg = $12;
  100. last_imreg = $ff;
  101. {Sub register numbers:}
  102. R_SUBL = $00; {Like AL}
  103. R_SUBH = $01; {Like AH}
  104. R_SUBW = $02; {Like AX}
  105. R_SUBD = $03; {Like EAX}
  106. R_SUBQ = $04; {Like RAX}
  107. {The subregister that specifies the entire register.}
  108. R_SUBWHOLE = R_SUBD; {i386}
  109. {R_SUBWHOLE = R_SUBQ;} {Hammer}
  110. {Special registers:}
  111. const NR_NO = $0000; {Invalid register}
  112. NR_CS = $0001; {CS}
  113. NR_DS = $0002; {DS}
  114. NR_ES = $0003; {ES}
  115. NR_SS = $0004; {SS}
  116. NR_FS = $0005; {FS}
  117. NR_GS = $0006; {GS}
  118. NR_RIP = $000F; {RIP}
  119. NR_DR0 = $0010; {DR0}
  120. NR_DR1 = $0011; {DR1}
  121. NR_DR2 = $0012; {DR2}
  122. NR_DR3 = $0013; {DR3}
  123. NR_DR6 = $0016; {DR6}
  124. NR_DR7 = $0017; {DR7}
  125. NR_CR0 = $0020; {CR0}
  126. NR_CR2 = $0021; {CR1}
  127. NR_CR3 = $0022; {CR2}
  128. NR_CR4 = $0023; {CR3}
  129. NR_TR3 = $0030; {R_TR3}
  130. NR_TR4 = $0031; {R_TR4}
  131. NR_TR5 = $0032; {R_TR5}
  132. NR_TR6 = $0033; {R_TR6}
  133. NR_TR7 = $0034; {R_TR7}
  134. {Normal registers.}
  135. const NR_AL = $0100; {AL}
  136. NR_AH = $0101; {AH}
  137. NR_AX = $0102; {AX}
  138. NR_EAX = $0103; {EAX}
  139. NR_RAX = $0104; {RAX}
  140. NR_BL = $0200; {BL}
  141. NR_BH = $0201; {BH}
  142. NR_BX = $0202; {BX}
  143. NR_EBX = $0203; {EBX}
  144. NR_RBX = $0204; {RBX}
  145. NR_CL = $0300; {CL}
  146. NR_CH = $0301; {CH}
  147. NR_CX = $0302; {CX}
  148. NR_ECX = $0303; {ECX}
  149. NR_RCX = $0304; {RCX}
  150. NR_DL = $0400; {DL}
  151. NR_DH = $0401; {DH}
  152. NR_DX = $0402; {DX}
  153. NR_EDX = $0403; {EDX}
  154. NR_RDX = $0404; {RDX}
  155. NR_SIL = $0500; {SIL}
  156. NR_SI = $0502; {SI}
  157. NR_ESI = $0503; {ESI}
  158. NR_RSI = $0504; {RSI}
  159. NR_DIL = $0600; {DIL}
  160. NR_DI = $0602; {DI}
  161. NR_EDI = $0603; {EDI}
  162. NR_RDI = $0604; {RDI}
  163. NR_BPL = $0700; {BPL}
  164. NR_BP = $0702; {BP}
  165. NR_EBP = $0703; {EBP}
  166. NR_RBP = $0704; {RBP}
  167. NR_SPL = $0800; {SPL}
  168. NR_SP = $0802; {SP}
  169. NR_ESP = $0803; {ESP}
  170. NR_RSP = $0804; {RSP}
  171. NR_R8L = $0900; {R8L}
  172. NR_R8W = $0902; {R8W}
  173. NR_R8D = $0903; {R8D}
  174. NR_R9L = $0a00; {R9D}
  175. NR_R9W = $0a02; {R9W}
  176. NR_R9D = $0a03; {R9D}
  177. NR_R10L = $0b00; {R10L}
  178. NR_R10W = $0b02; {R10W}
  179. NR_R10D = $0b03; {R10D}
  180. NR_R11L = $0c00; {R11L}
  181. NR_R11W = $0c02; {R11W}
  182. NR_R11D = $0c03; {R11D}
  183. NR_R12L = $0d00; {R12L}
  184. NR_R12W = $0d02; {R12W}
  185. NR_R12D = $0d03; {R12D}
  186. NR_R13L = $0e00; {R13L}
  187. NR_R13W = $0e02; {R13W}
  188. NR_R13D = $0e03; {R13D}
  189. NR_R14L = $0f00; {R14L}
  190. NR_R14W = $0f02; {R14W}
  191. NR_R14D = $0f03; {R14D}
  192. NR_R15L = $1000; {R15L}
  193. NR_R15W = $1002; {R15W}
  194. NR_R15D = $1003; {R15D}
  195. type
  196. {# Enumeration for all possible registers for cpu. It
  197. is to note that all registers of the same type
  198. (for example all FPU registers), should be grouped
  199. together.
  200. }
  201. { don't change the order }
  202. { it's used by the register size conversions }
  203. Toldregister = (R_NO,
  204. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  205. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  206. R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_BH,R_DH,
  207. R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
  208. R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
  209. R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
  210. R_CR0,R_CR2,R_CR3,R_CR4,
  211. R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
  212. R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
  213. R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7,
  214. R_INTREGISTER,R_FLOATREGISTER,R_MMXREGISTER,R_KNIREGISTER
  215. );
  216. type Tnewregister=word;
  217. Tregister = packed record
  218. enum:Toldregister;
  219. number:Tnewregister; {This is a word for now, change to cardinal
  220. when the old register coding is away.}
  221. end;
  222. Tsuperregister=byte;
  223. Tsubregister=byte;
  224. { A type to store register locations for 64 Bit values. }
  225. tregister64 = packed record
  226. reglo,reghi : tregister;
  227. end;
  228. { alias for compact code }
  229. treg64 = tregister64;
  230. {# Set type definition for registers }
  231. tregisterset = set of Toldregister;
  232. Tsupregset = set of Tsuperregister;
  233. const
  234. {# First register in the tregister enumeration }
  235. firstreg = low(Toldregister);
  236. {# Last register in the tregister enumeration }
  237. lastreg = R_XMM7;
  238. firstsreg = R_CS;
  239. lastsreg = R_GS;
  240. nfirstsreg = NR_CS;
  241. nlastsreg = NR_GS;
  242. regset8bit : tregisterset = [R_AL..R_DH];
  243. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  244. regset32bit : tregisterset = [R_EAX..R_EDI];
  245. {# Standard opcode string table (for each tasmop enumeration). The
  246. opcode strings should conform to the names as defined by the
  247. processor manufacturer.
  248. }
  249. std_op2str:op2strtable={$i i386int.inc}
  250. type
  251. {# Type definition for the array of string of register names }
  252. reg2strtable = array[firstreg..lastreg] of string[6];
  253. regname2regnumrec = record
  254. name:string[6];
  255. number:Tnewregister;
  256. end;
  257. const
  258. {# Standard register table (for each tregister enumeration). The
  259. register strings should conform to the the names as defined
  260. by the processor manufacturer
  261. }
  262. std_reg2str : reg2strtable = ('',
  263. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  264. 'ax','cx','dx','bx','sp','bp','si','di',
  265. 'al','cl','dl','bl','ah','ch','bh','dh',
  266. 'cs','ds','es','ss','fs','gs',
  267. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  268. 'dr0','dr1','dr2','dr3','dr6','dr7',
  269. 'cr0','cr2','cr3','cr4',
  270. 'tr3','tr4','tr5','tr6','tr7',
  271. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  272. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  273. );
  274. {*****************************************************************************
  275. Conditions
  276. *****************************************************************************}
  277. type
  278. TAsmCond=(C_None,
  279. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  280. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  281. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  282. );
  283. const
  284. cond2str:array[TAsmCond] of string[3]=('',
  285. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  286. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  287. 'ns','nz','o','p','pe','po','s','z'
  288. );
  289. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  290. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  291. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  292. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  293. );
  294. {*****************************************************************************
  295. Flags
  296. *****************************************************************************}
  297. type
  298. 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);
  299. {*****************************************************************************
  300. Reference
  301. *****************************************************************************}
  302. type
  303. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  304. { reference record }
  305. preference = ^treference;
  306. treference = packed record
  307. segment,
  308. base,
  309. index : tregister;
  310. scalefactor : byte;
  311. offset : longint;
  312. symbol : tasmsymbol;
  313. offsetfixup : longint;
  314. options : trefoptions;
  315. end;
  316. { reference record }
  317. pparareference = ^tparareference;
  318. tparareference = packed record
  319. index : tregister;
  320. offset : longint;
  321. end;
  322. {*****************************************************************************
  323. Operands
  324. *****************************************************************************}
  325. { Types of operand }
  326. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  327. toper=record
  328. ot : longint;
  329. case typ : toptype of
  330. top_none : ();
  331. top_reg : (reg:tregister);
  332. top_ref : (ref:preference);
  333. top_const : (val:aword);
  334. top_symbol : (sym:tasmsymbol;symofs:longint);
  335. end;
  336. {*****************************************************************************
  337. Generic Location
  338. *****************************************************************************}
  339. type
  340. { tparamlocation describes where a parameter for a procedure is stored.
  341. References are given from the caller's point of view. The usual
  342. TLocation isn't used, because contains a lot of unnessary fields.
  343. }
  344. tparalocation = packed record
  345. size : TCGSize;
  346. loc : TCGLoc;
  347. sp_fixup : longint;
  348. case TCGLoc of
  349. LOC_REFERENCE : (reference : tparareference);
  350. { segment in reference at the same place as in loc_register }
  351. LOC_REGISTER,LOC_CREGISTER : (
  352. case longint of
  353. 1 : (register,registerhigh : tregister);
  354. { overlay a registerlow }
  355. 2 : (registerlow : tregister);
  356. { overlay a 64 Bit register type }
  357. 3 : (reg64 : tregister64);
  358. 4 : (register64 : tregister64);
  359. );
  360. { it's only for better handling }
  361. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  362. end;
  363. tlocation = packed record
  364. loc : TCGLoc;
  365. size : TCGSize;
  366. case TCGLoc of
  367. LOC_FLAGS : (resflags : tresflags);
  368. LOC_CONSTANT : (
  369. case longint of
  370. 1 : (value : AWord);
  371. { can't do this, this layout depends on the host cpu. Use }
  372. { lo(valueqword)/hi(valueqword) instead (JM) }
  373. { 2 : (valuelow, valuehigh:AWord); }
  374. { overlay a complete 64 Bit value }
  375. 3 : (valueqword : qword);
  376. );
  377. LOC_CREFERENCE,
  378. LOC_REFERENCE : (reference : treference);
  379. { segment in reference at the same place as in loc_register }
  380. LOC_REGISTER,LOC_CREGISTER : (
  381. case longint of
  382. 1 : (register,registerhigh,segment : tregister);
  383. { overlay a registerlow }
  384. 2 : (registerlow : tregister);
  385. { overlay a 64 Bit register type }
  386. 3 : (reg64 : tregister64);
  387. 4 : (register64 : tregister64);
  388. );
  389. { it's only for better handling }
  390. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  391. end;
  392. {*****************************************************************************
  393. Constants
  394. *****************************************************************************}
  395. const
  396. { declare aliases }
  397. LOC_MMREGISTER = LOC_SSEREGISTER;
  398. LOC_CMMREGISTER = LOC_CSSEREGISTER;
  399. max_operands = 3;
  400. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  401. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  402. {# Constant defining possibly all registers which might require saving }
  403. ALL_REGISTERS = [firstreg..lastreg];
  404. ALL_INTREGISTERS = [1..255];
  405. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  406. general_superregisters = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
  407. {# low and high of the available maximum width integer general purpose }
  408. { registers }
  409. LoGPReg = R_EAX;
  410. HiGPReg = R_EDX;
  411. {# low and high of every possible width general purpose register (same as }
  412. { above on most architctures apart from the 80x86) }
  413. LoReg = R_EAX;
  414. HiReg = R_DH;
  415. {# Table of registers which can be allocated by the code generator
  416. internally, when generating the code.
  417. }
  418. { legend: }
  419. { xxxregs = set of all possibly used registers of that type in the code }
  420. { generator }
  421. { usableregsxxx = set of all 32bit components of registers that can be }
  422. { possible allocated to a regvar or using getregisterxxx (this }
  423. { excludes registers which can be only used for parameter }
  424. { passing on ABI's that define this) }
  425. { c_countusableregsxxx = amount of registers in the usableregsxxx set }
  426. maxintregs = 4;
  427. intregs = [R_EAX..R_BL]-[R_ESI,R_SI];
  428. {$ifdef newra}
  429. usableregsint = [first_imreg..last_imreg];
  430. {$else}
  431. usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
  432. {$endif}
  433. c_countusableregsint = 4;
  434. maxfpuregs = 8;
  435. fpuregs = [R_ST0..R_ST7];
  436. usableregsfpu = [];
  437. c_countusableregsfpu = 0;
  438. mmregs = [R_MM0..R_MM7];
  439. usableregsmm = [R_MM0..R_MM7];
  440. c_countusableregsmm = 8;
  441. maxaddrregs = 1;
  442. addrregs = [R_ESI];
  443. usableregsaddr = [RS_ESI];
  444. c_countusableregsaddr = 1;
  445. firstsaveintreg = RS_EAX;
  446. lastsaveintreg = RS_EDX;
  447. firstsavefpureg = R_NO;
  448. lastsavefpureg = R_NO;
  449. firstsavemmreg = R_MM0;
  450. lastsavemmreg = R_MM7;
  451. maxvarregs = 4;
  452. varregs : array[1..maxvarregs] of Toldregister =
  453. (R_EBX,R_EDX,R_ECX,R_EAX);
  454. maxfpuvarregs = 8;
  455. {# Registers which are defined as scratch and no need to save across
  456. routine calls or in assembler blocks.
  457. }
  458. {$ifndef newra}
  459. max_scratch_regs = 1;
  460. scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
  461. {$endif}
  462. {*****************************************************************************
  463. GDB Information
  464. *****************************************************************************}
  465. {# Register indexes for stabs information, when some
  466. parameters or variables are stored in registers.
  467. Taken from i386.c (dbx_register_map) and i386.h
  468. (FIXED_REGISTERS) from GCC 3.x source code
  469. }
  470. stab_regindex : array[firstreg..lastreg] of shortint =
  471. (-1,
  472. 0,1,2,3,4,5,6,7,
  473. 0,1,2,3,4,5,6,7,
  474. 0,1,2,3,0,1,2,3,
  475. -1,-1,-1,-1,-1,-1,
  476. 12,12,13,14,15,16,17,18,19,
  477. -1,-1,-1,-1,-1,-1,
  478. -1,-1,-1,-1,
  479. -1,-1,-1,-1,-1,
  480. 29,30,31,32,33,34,35,36,
  481. 21,22,23,24,25,26,27,28
  482. );
  483. {*****************************************************************************
  484. Default generic sizes
  485. *****************************************************************************}
  486. {# Defines the default address size for a processor, }
  487. OS_ADDR = OS_32;
  488. {# the natural int size for a processor, }
  489. OS_INT = OS_32;
  490. {# the maximum float size for a processor, }
  491. OS_FLOAT = OS_F80;
  492. {# the size of a vector register for a processor }
  493. OS_VECTOR = OS_M64;
  494. {*****************************************************************************
  495. Generic Register names
  496. *****************************************************************************}
  497. {# Stack pointer register }
  498. stack_pointer_reg = R_ESP;
  499. NR_STACK_POINTER_REG = NR_ESP;
  500. {# Frame pointer register }
  501. frame_pointer_reg = R_EBP;
  502. NR_FRAME_POINTER_REG = NR_EBP;
  503. {# Register for addressing absolute data in a position independant way,
  504. such as in PIC code. The exact meaning is ABI specific. For
  505. further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
  506. }
  507. pic_offset_reg = R_EBX;
  508. {# Results are returned in this register (32-bit values) }
  509. accumulator = R_EAX;
  510. RS_ACCUMULATOR = RS_EAX;
  511. NR_ACCUMULATOR = NR_EAX;
  512. {the return_result_reg, is used inside the called function to store its return
  513. value when that is a scalar value otherwise a pointer to the address of the
  514. result is placed inside it}
  515. return_result_reg = accumulator;
  516. RS_RETURN_RESULT_REG = RS_ACCUMULATOR;
  517. NR_RETURN_RESULT_REG = NR_ACCUMULATOR;
  518. {the function_result_reg contains the function result after a call to a scalar
  519. function othewise it contains a pointer to the returned result}
  520. function_result_reg = accumulator;
  521. {# Hi-Results are returned in this register (64-bit value high register) }
  522. accumulatorhigh = R_EDX;
  523. RS_ACCUMULATORHIGH = RS_EDX;
  524. NR_ACCUMULATORHIGH = NR_EDX;
  525. { WARNING: don't change to R_ST0!! See comments above implementation of }
  526. { a_loadfpu* methods in rgcpu (JM) }
  527. fpu_result_reg = R_ST;
  528. mmresultreg = R_MM0;
  529. {*****************************************************************************
  530. GCC /ABI linking information
  531. *****************************************************************************}
  532. const
  533. {# Registers which must be saved when calling a routine declared as
  534. cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
  535. saved should be the ones as defined in the target ABI and / or GCC.
  536. This value can be deduced from the CALLED_USED_REGISTERS array in the
  537. GCC source.
  538. }
  539. std_saved_registers = [R_ESI,R_EDI,R_EBX];
  540. {# Required parameter alignment when calling a routine declared as
  541. stdcall and cdecl. The alignment value should be the one defined
  542. by GCC or the target ABI.
  543. The value of this constant is equal to the constant
  544. PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
  545. }
  546. std_param_align = 4;
  547. {*****************************************************************************
  548. CPU Dependent Constants
  549. *****************************************************************************}
  550. {*****************************************************************************
  551. Helpers
  552. *****************************************************************************}
  553. procedure convert_register_to_enum(var r:Tregister);
  554. function cgsize2subreg(s:Tcgsize):Tsubregister;
  555. function reg2opsize(r:Tregister):topsize;
  556. function is_calljmp(o:tasmop):boolean;
  557. function flags_to_cond(const f: TResFlags) : TAsmCond;
  558. implementation
  559. uses verbose;
  560. {*****************************************************************************
  561. Helpers
  562. *****************************************************************************}
  563. procedure convert_register_to_enum(var r:Tregister);
  564. begin
  565. if r.enum=R_INTREGISTER then
  566. case r.number of
  567. NR_NO: r.enum:=R_NO;
  568. NR_EAX: r.enum:=R_EAX; NR_EBX: r.enum:=R_EBX;
  569. NR_ECX: r.enum:=R_ECX; NR_EDX: r.enum:=R_EDX;
  570. NR_ESI: r.enum:=R_ESI; NR_EDI: r.enum:=R_EDI;
  571. NR_ESP: r.enum:=R_ESP; NR_EBP: r.enum:=R_EBP;
  572. NR_AX: r.enum:=R_AX; NR_BX: r.enum:=R_BX;
  573. NR_CX: r.enum:=R_CX; NR_DX: r.enum:=R_DX;
  574. NR_SI: r.enum:=R_SI; NR_DI: r.enum:=R_DI;
  575. NR_SP: r.enum:=R_SP; NR_BP: r.enum:=R_BP;
  576. NR_AL: r.enum:=R_AL; NR_BL: r.enum:=R_BL;
  577. NR_CL: r.enum:=R_CL; NR_DL: r.enum:=R_DL;
  578. NR_AH: r.enum:=R_AH; NR_BH: r.enum:=R_BH;
  579. NR_CH: r.enum:=R_CH; NR_DH: r.enum:=R_DH;
  580. NR_CS: r.enum:=R_CS; NR_DS: r.enum:=R_DS;
  581. NR_ES: r.enum:=R_ES; NR_FS: r.enum:=R_FS;
  582. NR_GS: r.enum:=R_GS; NR_SS: r.enum:=R_SS;
  583. else
  584. internalerror(200301082);
  585. end;
  586. end;
  587. function cgsize2subreg(s:Tcgsize):Tsubregister;
  588. begin
  589. case s of
  590. OS_8,OS_S8:
  591. cgsize2subreg:=R_SUBL;
  592. OS_16,OS_S16:
  593. cgsize2subreg:=R_SUBW;
  594. OS_32,OS_S32:
  595. cgsize2subreg:=R_SUBD;
  596. OS_64,OS_S64:
  597. cgsize2subreg:=R_SUBQ;
  598. else
  599. internalerror(200301231);
  600. end;
  601. end;
  602. function reg2opsize(r:Tregister):topsize;
  603. const
  604. subreg2opsize : array[0..4] of Topsize = (S_B,S_B,S_W,S_L,S_D);
  605. enum2opsize : array[firstreg..lastreg] of topsize = (S_NO,
  606. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  607. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  608. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  609. S_W,S_W,S_W,S_W,S_W,S_W,
  610. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  611. S_L,S_L,S_L,S_L,S_L,S_L,
  612. S_L,S_L,S_L,S_L,
  613. S_L,S_L,S_L,S_L,S_L,
  614. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  615. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  616. );
  617. begin
  618. reg2opsize:=S_L;
  619. if (r.enum=R_INTREGISTER) then
  620. begin
  621. if (r.number shr 8)=0 then
  622. begin
  623. case r.number of
  624. NR_CS,NR_DS,NR_ES,
  625. NR_SS,NR_FS,NR_GS :
  626. reg2opsize:=S_W;
  627. end;
  628. end
  629. else
  630. begin
  631. if (r.number and $ff)>4 then
  632. internalerror(200303181);
  633. reg2opsize:=subreg2opsize[r.number and $ff];
  634. end;
  635. end
  636. else
  637. begin
  638. reg2opsize:=enum2opsize[r.enum];
  639. end;
  640. end;
  641. {$ifdef unused}
  642. function supreg_name(r:Tsuperregister):string;
  643. var s:string[4];
  644. const supreg_names:array[0..last_supreg] of string[4]=
  645. ('INV',
  646. 'eax','ebx','ecx','edx','esi','edi','ebp','esp',
  647. 'r8' ,'r9', 'r10','r11','r12','r13','r14','r15');
  648. begin
  649. if r in [0..last_supreg] then
  650. supreg_name:=supreg_names[r]
  651. else
  652. begin
  653. str(r,s);
  654. supreg_name:='reg'+s;
  655. end;
  656. end;
  657. {$endif unused}
  658. function is_calljmp(o:tasmop):boolean;
  659. begin
  660. case o of
  661. A_CALL,
  662. A_JCXZ,
  663. A_JECXZ,
  664. A_JMP,
  665. A_LOOP,
  666. A_LOOPE,
  667. A_LOOPNE,
  668. A_LOOPNZ,
  669. A_LOOPZ,
  670. A_Jcc :
  671. is_calljmp:=true;
  672. else
  673. is_calljmp:=false;
  674. end;
  675. end;
  676. function flags_to_cond(const f: TResFlags) : TAsmCond;
  677. const
  678. flags_2_cond : array[TResFlags] of TAsmCond =
  679. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  680. begin
  681. result := flags_2_cond[f];
  682. end;
  683. end.
  684. {
  685. $Log$
  686. Revision 1.49 2003-04-22 23:50:23 peter
  687. * firstpass uses expectloc
  688. * checks if there are differences between the expectloc and
  689. location.loc from secondpass in EXTDEBUG
  690. Revision 1.48 2003/04/22 14:33:38 peter
  691. * removed some notes/hints
  692. Revision 1.47 2003/04/22 10:09:35 daniel
  693. + Implemented the actual register allocator
  694. + Scratch registers unavailable when new register allocator used
  695. + maybe_save/maybe_restore unavailable when new register allocator used
  696. Revision 1.46 2003/04/21 19:16:50 peter
  697. * count address regs separate
  698. Revision 1.45 2003/03/28 19:16:57 peter
  699. * generic constructor working for i386
  700. * remove fixed self register
  701. * esi added as address register for i386
  702. Revision 1.44 2003/03/18 18:15:53 peter
  703. * changed reg2opsize to function
  704. Revision 1.43 2003/03/08 08:59:07 daniel
  705. + $define newra will enable new register allocator
  706. + getregisterint will return imaginary registers with $newra
  707. + -sr switch added, will skip register allocation so you can see
  708. the direct output of the code generator before register allocation
  709. Revision 1.42 2003/02/19 22:00:15 daniel
  710. * Code generator converted to new register notation
  711. - Horribily outdated todo.txt removed
  712. Revision 1.41 2003/02/02 19:25:54 carl
  713. * Several bugfixes for m68k target (register alloc., opcode emission)
  714. + VIS target
  715. + Generic add more complete (still not verified)
  716. Revision 1.40 2003/01/13 18:37:44 daniel
  717. * Work on register conversion
  718. Revision 1.39 2003/01/09 20:41:00 daniel
  719. * Converted some code in cgx86.pas to new register numbering
  720. Revision 1.38 2003/01/09 15:49:56 daniel
  721. * Added register conversion
  722. Revision 1.37 2003/01/08 22:32:36 daniel
  723. * Added register convesrion procedure
  724. Revision 1.36 2003/01/08 18:43:57 daniel
  725. * Tregister changed into a record
  726. Revision 1.35 2003/01/05 13:36:53 florian
  727. * x86-64 compiles
  728. + very basic support for float128 type (x86-64 only)
  729. Revision 1.34 2002/11/17 18:26:16 mazen
  730. * fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
  731. Revision 1.33 2002/11/17 17:49:08 mazen
  732. + 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
  733. Revision 1.32 2002/10/05 12:43:29 carl
  734. * fixes for Delphi 6 compilation
  735. (warning : Some features do not work under Delphi)
  736. Revision 1.31 2002/08/14 18:41:48 jonas
  737. - remove valuelow/valuehigh fields from tlocation, because they depend
  738. on the endianess of the host operating system -> difficult to get
  739. right. Use lo/hi(location.valueqword) instead (remember to use
  740. valueqword and not value!!)
  741. Revision 1.30 2002/08/13 21:40:58 florian
  742. * more fixes for ppc calling conventions
  743. Revision 1.29 2002/08/12 15:08:41 carl
  744. + stab register indexes for powerpc (moved from gdb to cpubase)
  745. + tprocessor enumeration moved to cpuinfo
  746. + linker in target_info is now a class
  747. * many many updates for m68k (will soon start to compile)
  748. - removed some ifdef or correct them for correct cpu
  749. Revision 1.28 2002/08/06 20:55:23 florian
  750. * first part of ppc calling conventions fix
  751. Revision 1.27 2002/07/25 18:01:29 carl
  752. + FPURESULTREG -> FPU_RESULT_REG
  753. Revision 1.26 2002/07/07 09:52:33 florian
  754. * powerpc target fixed, very simple units can be compiled
  755. * some basic stuff for better callparanode handling, far from being finished
  756. Revision 1.25 2002/07/01 18:46:30 peter
  757. * internal linker
  758. * reorganized aasm layer
  759. Revision 1.24 2002/07/01 16:23:55 peter
  760. * cg64 patch
  761. * basics for currency
  762. * asnode updates for class and interface (not finished)
  763. Revision 1.23 2002/05/18 13:34:22 peter
  764. * readded missing revisions
  765. Revision 1.22 2002/05/16 19:46:50 carl
  766. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  767. + try to fix temp allocation (still in ifdef)
  768. + generic constructor calls
  769. + start of tassembler / tmodulebase class cleanup
  770. Revision 1.19 2002/05/12 16:53:16 peter
  771. * moved entry and exitcode to ncgutil and cgobj
  772. * foreach gets extra argument for passing local data to the
  773. iterator function
  774. * -CR checks also class typecasts at runtime by changing them
  775. into as
  776. * fixed compiler to cycle with the -CR option
  777. * fixed stabs with elf writer, finally the global variables can
  778. be watched
  779. * removed a lot of routines from cga unit and replaced them by
  780. calls to cgobj
  781. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  782. u32bit then the other is typecasted also to u32bit without giving
  783. a rangecheck warning/error.
  784. * fixed pascal calling method with reversing also the high tree in
  785. the parast, detected by tcalcst3 test
  786. Revision 1.18 2002/04/21 15:31:40 carl
  787. - removed some other stuff to their units
  788. Revision 1.17 2002/04/20 21:37:07 carl
  789. + generic FPC_CHECKPOINTER
  790. + first parameter offset in stack now portable
  791. * rename some constants
  792. + move some cpu stuff to other units
  793. - remove unused constents
  794. * fix stacksize for some targets
  795. * fix generic size problems which depend now on EXTEND_SIZE constant
  796. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  797. Revision 1.16 2002/04/15 19:53:54 peter
  798. * fixed conflicts between the last 2 commits
  799. Revision 1.15 2002/04/15 19:44:20 peter
  800. * fixed stackcheck that would be called recursively when a stack
  801. error was found
  802. * generic changeregsize(reg,size) for i386 register resizing
  803. * removed some more routines from cga unit
  804. * fixed returnvalue handling
  805. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  806. Revision 1.14 2002/04/15 19:12:09 carl
  807. + target_info.size_of_pointer -> pointer_size
  808. + some cleanup of unused types/variables
  809. * move several constants from cpubase to their specific units
  810. (where they are used)
  811. + att_Reg2str -> gas_reg2str
  812. + int_reg2str -> std_reg2str
  813. Revision 1.13 2002/04/14 16:59:41 carl
  814. + att_reg2str -> gas_reg2str
  815. Revision 1.12 2002/04/02 17:11:34 peter
  816. * tlocation,treference update
  817. * LOC_CONSTANT added for better constant handling
  818. * secondadd splitted in multiple routines
  819. * location_force_reg added for loading a location to a register
  820. of a specified size
  821. * secondassignment parses now first the right and then the left node
  822. (this is compatible with Kylix). This saves a lot of push/pop especially
  823. with string operations
  824. * adapted some routines to use the new cg methods
  825. Revision 1.11 2002/03/31 20:26:37 jonas
  826. + a_loadfpu_* and a_loadmm_* methods in tcg
  827. * register allocation is now handled by a class and is mostly processor
  828. independent (+rgobj.pas and i386/rgcpu.pas)
  829. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  830. * some small improvements and fixes to the optimizer
  831. * some register allocation fixes
  832. * some fpuvaroffset fixes in the unary minus node
  833. * push/popusedregisters is now called rg.save/restoreusedregisters and
  834. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  835. also better optimizable)
  836. * fixed and optimized register saving/restoring for new/dispose nodes
  837. * LOC_FPU locations now also require their "register" field to be set to
  838. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  839. - list field removed of the tnode class because it's not used currently
  840. and can cause hard-to-find bugs
  841. Revision 1.10 2002/03/04 19:10:12 peter
  842. * removed compiler warnings
  843. }