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. 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. {$packenum 1}
  204. Toldregister = (R_NO,
  205. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  206. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  207. R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_BH,R_DH,
  208. R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
  209. R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
  210. R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
  211. R_CR0,R_CR2,R_CR3,R_CR4,
  212. R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
  213. R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
  214. R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7,
  215. R_INTREGISTER,R_FLOATREGISTER,R_MMXREGISTER,R_KNIREGISTER
  216. );
  217. type Tnewregister=word;
  218. Tregister = packed record
  219. enum:Toldregister;
  220. number:Tnewregister; {This is a word for now, change to cardinal
  221. when the old register coding is away.}
  222. end;
  223. Tsuperregister=byte;
  224. Tsubregister=byte;
  225. {$packenum normal}
  226. { A type to store register locations for 64 Bit values. }
  227. tregister64 = packed record
  228. reglo,reghi : tregister;
  229. end;
  230. { alias for compact code }
  231. treg64 = tregister64;
  232. {# Set type definition for registers }
  233. tregisterset = set of Toldregister;
  234. Tsupregset = set of Tsuperregister;
  235. const
  236. {# First register in the tregister enumeration }
  237. firstreg = low(Toldregister);
  238. {# Last register in the tregister enumeration }
  239. lastreg = R_XMM7;
  240. firstsreg = R_CS;
  241. lastsreg = R_GS;
  242. nfirstsreg = NR_CS;
  243. nlastsreg = NR_GS;
  244. regset8bit : tregisterset = [R_AL..R_DH];
  245. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  246. regset32bit : tregisterset = [R_EAX..R_EDI];
  247. {# Standard opcode string table (for each tasmop enumeration). The
  248. opcode strings should conform to the names as defined by the
  249. processor manufacturer.
  250. }
  251. std_op2str:op2strtable={$i i386int.inc}
  252. type
  253. {# Type definition for the array of string of register names }
  254. reg2strtable = array[firstreg..lastreg] of string[6];
  255. regname2regnumrec = record
  256. name:string[6];
  257. number:Tnewregister;
  258. end;
  259. const
  260. {# Standard register table (for each tregister enumeration). The
  261. register strings should conform to the the names as defined
  262. by the processor manufacturer
  263. }
  264. std_reg2str : reg2strtable = ('',
  265. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  266. 'ax','cx','dx','bx','sp','bp','si','di',
  267. 'al','cl','dl','bl','ah','ch','bh','dh',
  268. 'cs','ds','es','ss','fs','gs',
  269. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  270. 'dr0','dr1','dr2','dr3','dr6','dr7',
  271. 'cr0','cr2','cr3','cr4',
  272. 'tr3','tr4','tr5','tr6','tr7',
  273. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  274. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  275. );
  276. {*****************************************************************************
  277. Conditions
  278. *****************************************************************************}
  279. type
  280. TAsmCond=(C_None,
  281. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  282. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  283. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  284. );
  285. const
  286. cond2str:array[TAsmCond] of string[3]=('',
  287. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  288. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  289. 'ns','nz','o','p','pe','po','s','z'
  290. );
  291. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  292. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  293. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  294. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  295. );
  296. {*****************************************************************************
  297. Flags
  298. *****************************************************************************}
  299. type
  300. 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);
  301. {*****************************************************************************
  302. Reference
  303. *****************************************************************************}
  304. type
  305. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  306. { reference record }
  307. preference = ^treference;
  308. treference = packed record
  309. segment,
  310. base,
  311. index : tregister;
  312. scalefactor : byte;
  313. offset : longint;
  314. symbol : tasmsymbol;
  315. offsetfixup : longint;
  316. options : trefoptions;
  317. end;
  318. { reference record }
  319. pparareference = ^tparareference;
  320. tparareference = packed record
  321. index : tregister;
  322. offset : longint;
  323. end;
  324. {*****************************************************************************
  325. Operands
  326. *****************************************************************************}
  327. { Types of operand }
  328. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  329. toper=record
  330. ot : longint;
  331. case typ : toptype of
  332. top_none : ();
  333. top_reg : (reg:tregister);
  334. top_ref : (ref:preference);
  335. top_const : (val:aword);
  336. top_symbol : (sym:tasmsymbol;symofs:longint);
  337. end;
  338. {*****************************************************************************
  339. Generic Location
  340. *****************************************************************************}
  341. type
  342. TLoc=(
  343. LOC_INVALID, { added for tracking problems}
  344. LOC_CONSTANT, { constant value }
  345. LOC_JUMP, { boolean results only, jump to false or true label }
  346. LOC_FLAGS, { boolean results only, flags are set }
  347. LOC_CREFERENCE, { in memory constant value reference (cannot change) }
  348. LOC_REFERENCE, { in memory value }
  349. LOC_REGISTER, { in a processor register }
  350. LOC_CREGISTER, { Constant register which shouldn't be modified }
  351. LOC_FPUREGISTER, { FPU stack }
  352. LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
  353. LOC_MMXREGISTER, { MMX register }
  354. LOC_CMMXREGISTER, { MMX register variable }
  355. LOC_SSEREGISTER,
  356. LOC_CSSEREGISTER
  357. );
  358. { tparamlocation describes where a parameter for a procedure is stored.
  359. References are given from the caller's point of view. The usual
  360. TLocation isn't used, because contains a lot of unnessary fields.
  361. }
  362. tparalocation = packed record
  363. size : TCGSize;
  364. loc : TLoc;
  365. sp_fixup : longint;
  366. case TLoc of
  367. LOC_REFERENCE : (reference : tparareference);
  368. { segment in reference at the same place as in loc_register }
  369. LOC_REGISTER,LOC_CREGISTER : (
  370. case longint of
  371. 1 : (register,registerhigh : tregister);
  372. { overlay a registerlow }
  373. 2 : (registerlow : tregister);
  374. { overlay a 64 Bit register type }
  375. 3 : (reg64 : tregister64);
  376. 4 : (register64 : tregister64);
  377. );
  378. { it's only for better handling }
  379. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  380. end;
  381. tlocation = packed record
  382. loc : TLoc;
  383. size : TCGSize;
  384. case TLoc of
  385. LOC_FLAGS : (resflags : tresflags);
  386. LOC_CONSTANT : (
  387. case longint of
  388. 1 : (value : AWord);
  389. { can't do this, this layout depends on the host cpu. Use }
  390. { lo(valueqword)/hi(valueqword) instead (JM) }
  391. { 2 : (valuelow, valuehigh:AWord); }
  392. { overlay a complete 64 Bit value }
  393. 3 : (valueqword : qword);
  394. );
  395. LOC_CREFERENCE,
  396. LOC_REFERENCE : (reference : treference);
  397. { segment in reference at the same place as in loc_register }
  398. LOC_REGISTER,LOC_CREGISTER : (
  399. case longint of
  400. 1 : (register,registerhigh,segment : tregister);
  401. { overlay a registerlow }
  402. 2 : (registerlow : tregister);
  403. { overlay a 64 Bit register type }
  404. 3 : (reg64 : tregister64);
  405. 4 : (register64 : tregister64);
  406. );
  407. { it's only for better handling }
  408. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  409. end;
  410. {*****************************************************************************
  411. Constants
  412. *****************************************************************************}
  413. const
  414. { declare aliases }
  415. LOC_MMREGISTER = LOC_SSEREGISTER;
  416. LOC_CMMREGISTER = LOC_CSSEREGISTER;
  417. max_operands = 3;
  418. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  419. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  420. {# Constant defining possibly all registers which might require saving }
  421. ALL_REGISTERS = [firstreg..lastreg];
  422. ALL_INTREGISTERS = [1..255];
  423. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  424. general_superregisters = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
  425. {# low and high of the available maximum width integer general purpose }
  426. { registers }
  427. LoGPReg = R_EAX;
  428. HiGPReg = R_EDX;
  429. {# low and high of every possible width general purpose register (same as }
  430. { above on most architctures apart from the 80x86) }
  431. LoReg = R_EAX;
  432. HiReg = R_DH;
  433. {# Table of registers which can be allocated by the code generator
  434. internally, when generating the code.
  435. }
  436. { legend: }
  437. { xxxregs = set of all possibly used registers of that type in the code }
  438. { generator }
  439. { usableregsxxx = set of all 32bit components of registers that can be }
  440. { possible allocated to a regvar or using getregisterxxx (this }
  441. { excludes registers which can be only used for parameter }
  442. { passing on ABI's that define this) }
  443. { c_countusableregsxxx = amount of registers in the usableregsxxx set }
  444. maxintregs = 4;
  445. intregs = [R_EAX..R_BL];
  446. {$ifdef newra}
  447. usableregsint = [first_imreg..last_imreg];
  448. {$else}
  449. usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI];
  450. {$endif}
  451. c_countusableregsint = 5;
  452. maxfpuregs = 8;
  453. fpuregs = [R_ST0..R_ST7];
  454. usableregsfpu = [];
  455. c_countusableregsfpu = 0;
  456. mmregs = [R_MM0..R_MM7];
  457. usableregsmm = [R_MM0..R_MM7];
  458. c_countusableregsmm = 8;
  459. maxaddrregs = 0;
  460. addrregs = [];
  461. usableregsaddr = [];
  462. c_countusableregsaddr = 0;
  463. firstsaveintreg = RS_EAX;
  464. lastsaveintreg = RS_ESI;
  465. firstsavefpureg = R_NO;
  466. lastsavefpureg = R_NO;
  467. firstsavemmreg = R_MM0;
  468. lastsavemmreg = R_MM7;
  469. maxvarregs = 4;
  470. varregs : array[1..maxvarregs] of Toldregister =
  471. (R_EBX,R_EDX,R_ECX,R_EAX);
  472. maxfpuvarregs = 8;
  473. {# Registers which are defined as scratch and no need to save across
  474. routine calls or in assembler blocks.
  475. }
  476. max_scratch_regs = 1;
  477. scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
  478. {*****************************************************************************
  479. GDB Information
  480. *****************************************************************************}
  481. {# Register indexes for stabs information, when some
  482. parameters or variables are stored in registers.
  483. Taken from i386.c (dbx_register_map) and i386.h
  484. (FIXED_REGISTERS) from GCC 3.x source code
  485. }
  486. stab_regindex : array[firstreg..lastreg] of shortint =
  487. (-1,
  488. 0,1,2,3,4,5,6,7,
  489. 0,1,2,3,4,5,6,7,
  490. 0,1,2,3,0,1,2,3,
  491. -1,-1,-1,-1,-1,-1,
  492. 12,12,13,14,15,16,17,18,19,
  493. -1,-1,-1,-1,-1,-1,
  494. -1,-1,-1,-1,
  495. -1,-1,-1,-1,-1,
  496. 29,30,31,32,33,34,35,36,
  497. 21,22,23,24,25,26,27,28
  498. );
  499. {*****************************************************************************
  500. Default generic sizes
  501. *****************************************************************************}
  502. {# Defines the default address size for a processor, }
  503. OS_ADDR = OS_32;
  504. {# the natural int size for a processor, }
  505. OS_INT = OS_32;
  506. {# the maximum float size for a processor, }
  507. OS_FLOAT = OS_F80;
  508. {# the size of a vector register for a processor }
  509. OS_VECTOR = OS_M64;
  510. {*****************************************************************************
  511. Generic Register names
  512. *****************************************************************************}
  513. {# Stack pointer register }
  514. stack_pointer_reg = R_ESP;
  515. NR_STACK_POINTER_REG = NR_ESP;
  516. {# Frame pointer register }
  517. frame_pointer_reg = R_EBP;
  518. NR_FRAME_POINTER_REG = NR_EBP;
  519. {# Register for addressing absolute data in a position independant way,
  520. such as in PIC code. The exact meaning is ABI specific. For
  521. further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
  522. }
  523. pic_offset_reg = R_EBX;
  524. {# Results are returned in this register (32-bit values) }
  525. accumulator = R_EAX;
  526. RS_ACCUMULATOR = RS_EAX;
  527. NR_ACCUMULATOR = NR_EAX;
  528. {the return_result_reg, is used inside the called function to store its return
  529. value when that is a scalar value otherwise a pointer to the address of the
  530. result is placed inside it}
  531. return_result_reg = accumulator;
  532. RS_RETURN_RESULT_REG = RS_ACCUMULATOR;
  533. NR_RETURN_RESULT_REG = NR_ACCUMULATOR;
  534. {the function_result_reg contains the function result after a call to a scalar
  535. function othewise it contains a pointer to the returned result}
  536. function_result_reg = accumulator;
  537. {# Hi-Results are returned in this register (64-bit value high register) }
  538. accumulatorhigh = R_EDX;
  539. RS_ACCUMULATORHIGH = RS_EDX;
  540. NR_ACCUMULATORHIGH = NR_EDX;
  541. { WARNING: don't change to R_ST0!! See comments above implementation of }
  542. { a_loadfpu* methods in rgcpu (JM) }
  543. fpu_result_reg = R_ST;
  544. mmresultreg = R_MM0;
  545. {*****************************************************************************
  546. GCC /ABI linking information
  547. *****************************************************************************}
  548. const
  549. {# Registers which must be saved when calling a routine declared as
  550. cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
  551. saved should be the ones as defined in the target ABI and / or GCC.
  552. This value can be deduced from the CALLED_USED_REGISTERS array in the
  553. GCC source.
  554. }
  555. std_saved_registers = [R_ESI,R_EDI,R_EBX];
  556. {# Required parameter alignment when calling a routine declared as
  557. stdcall and cdecl. The alignment value should be the one defined
  558. by GCC or the target ABI.
  559. The value of this constant is equal to the constant
  560. PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
  561. }
  562. std_param_align = 4;
  563. {*****************************************************************************
  564. CPU Dependent Constants
  565. *****************************************************************************}
  566. {*****************************************************************************
  567. Helpers
  568. *****************************************************************************}
  569. procedure convert_register_to_enum(var r:Tregister);
  570. function cgsize2subreg(s:Tcgsize):Tsubregister;
  571. function reg2opsize(r:Tregister):topsize;
  572. function is_calljmp(o:tasmop):boolean;
  573. function flags_to_cond(const f: TResFlags) : TAsmCond;
  574. implementation
  575. uses verbose;
  576. {*****************************************************************************
  577. Helpers
  578. *****************************************************************************}
  579. procedure convert_register_to_enum(var r:Tregister);
  580. begin
  581. if r.enum=R_INTREGISTER then
  582. case r.number of
  583. NR_NO: r.enum:=R_NO;
  584. NR_EAX: r.enum:=R_EAX; NR_EBX: r.enum:=R_EBX;
  585. NR_ECX: r.enum:=R_ECX; NR_EDX: r.enum:=R_EDX;
  586. NR_ESI: r.enum:=R_ESI; NR_EDI: r.enum:=R_EDI;
  587. NR_ESP: r.enum:=R_ESP; NR_EBP: r.enum:=R_EBP;
  588. NR_AX: r.enum:=R_AX; NR_BX: r.enum:=R_BX;
  589. NR_CX: r.enum:=R_CX; NR_DX: r.enum:=R_DX;
  590. NR_SI: r.enum:=R_SI; NR_DI: r.enum:=R_DI;
  591. NR_SP: r.enum:=R_SP; NR_BP: r.enum:=R_BP;
  592. NR_AL: r.enum:=R_AL; NR_BL: r.enum:=R_BL;
  593. NR_CL: r.enum:=R_CL; NR_DL: r.enum:=R_DL;
  594. NR_AH: r.enum:=R_AH; NR_BH: r.enum:=R_BH;
  595. NR_CH: r.enum:=R_CH; NR_DH: r.enum:=R_DH;
  596. NR_CS: r.enum:=R_CS; NR_DS: r.enum:=R_DS;
  597. NR_ES: r.enum:=R_ES; NR_FS: r.enum:=R_FS;
  598. NR_GS: r.enum:=R_GS; NR_SS: r.enum:=R_SS;
  599. else
  600. internalerror(200301082);
  601. end;
  602. end;
  603. function cgsize2subreg(s:Tcgsize):Tsubregister;
  604. begin
  605. case s of
  606. OS_8,OS_S8:
  607. cgsize2subreg:=R_SUBL;
  608. OS_16,OS_S16:
  609. cgsize2subreg:=R_SUBW;
  610. OS_32,OS_S32:
  611. cgsize2subreg:=R_SUBD;
  612. OS_64,OS_S64:
  613. cgsize2subreg:=R_SUBQ;
  614. else
  615. internalerror(200301231);
  616. end;
  617. end;
  618. function reg2opsize(r:Tregister):topsize;
  619. const
  620. subreg2opsize : array[0..4] of Topsize = (S_B,S_B,S_W,S_L,S_D);
  621. enum2opsize : array[firstreg..lastreg] of topsize = (S_NO,
  622. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  623. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  624. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  625. S_W,S_W,S_W,S_W,S_W,S_W,
  626. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  627. S_L,S_L,S_L,S_L,S_L,S_L,
  628. S_L,S_L,S_L,S_L,
  629. S_L,S_L,S_L,S_L,S_L,
  630. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  631. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  632. );
  633. begin
  634. reg2opsize:=S_L;
  635. if (r.enum=R_INTREGISTER) then
  636. begin
  637. if (r.number shr 8)=0 then
  638. begin
  639. case r.number of
  640. NR_CS,NR_DS,NR_ES,
  641. NR_SS,NR_FS,NR_GS :
  642. reg2opsize:=S_W;
  643. end;
  644. end
  645. else
  646. begin
  647. if (r.number and $ff)>4 then
  648. internalerror(200303181);
  649. reg2opsize:=subreg2opsize[r.number and $ff];
  650. end;
  651. end
  652. else
  653. begin
  654. reg2opsize:=enum2opsize[r.enum];
  655. end;
  656. end;
  657. function supreg_name(r:Tsuperregister):string;
  658. var s:string[4];
  659. const supreg_names:array[0..last_supreg] of string[4]=
  660. ('INV',
  661. 'eax','ebx','ecx','edx','esi','edi','ebp','esp',
  662. 'r8' ,'r9', 'r10','r11','r12','r13','r14','r15');
  663. begin
  664. if r in [0..last_supreg] then
  665. supreg_name:=supreg_names[r]
  666. else
  667. begin
  668. str(r,s);
  669. supreg_name:='reg'+s;
  670. end;
  671. end;
  672. function is_calljmp(o:tasmop):boolean;
  673. begin
  674. case o of
  675. A_CALL,
  676. A_JCXZ,
  677. A_JECXZ,
  678. A_JMP,
  679. A_LOOP,
  680. A_LOOPE,
  681. A_LOOPNE,
  682. A_LOOPNZ,
  683. A_LOOPZ,
  684. A_Jcc :
  685. is_calljmp:=true;
  686. else
  687. is_calljmp:=false;
  688. end;
  689. end;
  690. function flags_to_cond(const f: TResFlags) : TAsmCond;
  691. const
  692. flags_2_cond : array[TResFlags] of TAsmCond =
  693. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  694. begin
  695. result := flags_2_cond[f];
  696. end;
  697. end.
  698. {
  699. $Log$
  700. Revision 1.45 2003-03-28 19:16:57 peter
  701. * generic constructor working for i386
  702. * remove fixed self register
  703. * esi added as address register for i386
  704. Revision 1.44 2003/03/18 18:15:53 peter
  705. * changed reg2opsize to function
  706. Revision 1.43 2003/03/08 08:59:07 daniel
  707. + $define newra will enable new register allocator
  708. + getregisterint will return imaginary registers with $newra
  709. + -sr switch added, will skip register allocation so you can see
  710. the direct output of the code generator before register allocation
  711. Revision 1.42 2003/02/19 22:00:15 daniel
  712. * Code generator converted to new register notation
  713. - Horribily outdated todo.txt removed
  714. Revision 1.41 2003/02/02 19:25:54 carl
  715. * Several bugfixes for m68k target (register alloc., opcode emission)
  716. + VIS target
  717. + Generic add more complete (still not verified)
  718. Revision 1.40 2003/01/13 18:37:44 daniel
  719. * Work on register conversion
  720. Revision 1.39 2003/01/09 20:41:00 daniel
  721. * Converted some code in cgx86.pas to new register numbering
  722. Revision 1.38 2003/01/09 15:49:56 daniel
  723. * Added register conversion
  724. Revision 1.37 2003/01/08 22:32:36 daniel
  725. * Added register convesrion procedure
  726. Revision 1.36 2003/01/08 18:43:57 daniel
  727. * Tregister changed into a record
  728. Revision 1.35 2003/01/05 13:36:53 florian
  729. * x86-64 compiles
  730. + very basic support for float128 type (x86-64 only)
  731. Revision 1.34 2002/11/17 18:26:16 mazen
  732. * fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
  733. Revision 1.33 2002/11/17 17:49:08 mazen
  734. + 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
  735. Revision 1.32 2002/10/05 12:43:29 carl
  736. * fixes for Delphi 6 compilation
  737. (warning : Some features do not work under Delphi)
  738. Revision 1.31 2002/08/14 18:41:48 jonas
  739. - remove valuelow/valuehigh fields from tlocation, because they depend
  740. on the endianess of the host operating system -> difficult to get
  741. right. Use lo/hi(location.valueqword) instead (remember to use
  742. valueqword and not value!!)
  743. Revision 1.30 2002/08/13 21:40:58 florian
  744. * more fixes for ppc calling conventions
  745. Revision 1.29 2002/08/12 15:08:41 carl
  746. + stab register indexes for powerpc (moved from gdb to cpubase)
  747. + tprocessor enumeration moved to cpuinfo
  748. + linker in target_info is now a class
  749. * many many updates for m68k (will soon start to compile)
  750. - removed some ifdef or correct them for correct cpu
  751. Revision 1.28 2002/08/06 20:55:23 florian
  752. * first part of ppc calling conventions fix
  753. Revision 1.27 2002/07/25 18:01:29 carl
  754. + FPURESULTREG -> FPU_RESULT_REG
  755. Revision 1.26 2002/07/07 09:52:33 florian
  756. * powerpc target fixed, very simple units can be compiled
  757. * some basic stuff for better callparanode handling, far from being finished
  758. Revision 1.25 2002/07/01 18:46:30 peter
  759. * internal linker
  760. * reorganized aasm layer
  761. Revision 1.24 2002/07/01 16:23:55 peter
  762. * cg64 patch
  763. * basics for currency
  764. * asnode updates for class and interface (not finished)
  765. Revision 1.23 2002/05/18 13:34:22 peter
  766. * readded missing revisions
  767. Revision 1.22 2002/05/16 19:46:50 carl
  768. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  769. + try to fix temp allocation (still in ifdef)
  770. + generic constructor calls
  771. + start of tassembler / tmodulebase class cleanup
  772. Revision 1.19 2002/05/12 16:53:16 peter
  773. * moved entry and exitcode to ncgutil and cgobj
  774. * foreach gets extra argument for passing local data to the
  775. iterator function
  776. * -CR checks also class typecasts at runtime by changing them
  777. into as
  778. * fixed compiler to cycle with the -CR option
  779. * fixed stabs with elf writer, finally the global variables can
  780. be watched
  781. * removed a lot of routines from cga unit and replaced them by
  782. calls to cgobj
  783. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  784. u32bit then the other is typecasted also to u32bit without giving
  785. a rangecheck warning/error.
  786. * fixed pascal calling method with reversing also the high tree in
  787. the parast, detected by tcalcst3 test
  788. Revision 1.18 2002/04/21 15:31:40 carl
  789. - removed some other stuff to their units
  790. Revision 1.17 2002/04/20 21:37:07 carl
  791. + generic FPC_CHECKPOINTER
  792. + first parameter offset in stack now portable
  793. * rename some constants
  794. + move some cpu stuff to other units
  795. - remove unused constents
  796. * fix stacksize for some targets
  797. * fix generic size problems which depend now on EXTEND_SIZE constant
  798. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  799. Revision 1.16 2002/04/15 19:53:54 peter
  800. * fixed conflicts between the last 2 commits
  801. Revision 1.15 2002/04/15 19:44:20 peter
  802. * fixed stackcheck that would be called recursively when a stack
  803. error was found
  804. * generic changeregsize(reg,size) for i386 register resizing
  805. * removed some more routines from cga unit
  806. * fixed returnvalue handling
  807. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  808. Revision 1.14 2002/04/15 19:12:09 carl
  809. + target_info.size_of_pointer -> pointer_size
  810. + some cleanup of unused types/variables
  811. * move several constants from cpubase to their specific units
  812. (where they are used)
  813. + att_Reg2str -> gas_reg2str
  814. + int_reg2str -> std_reg2str
  815. Revision 1.13 2002/04/14 16:59:41 carl
  816. + att_reg2str -> gas_reg2str
  817. Revision 1.12 2002/04/02 17:11:34 peter
  818. * tlocation,treference update
  819. * LOC_CONSTANT added for better constant handling
  820. * secondadd splitted in multiple routines
  821. * location_force_reg added for loading a location to a register
  822. of a specified size
  823. * secondassignment parses now first the right and then the left node
  824. (this is compatible with Kylix). This saves a lot of push/pop especially
  825. with string operations
  826. * adapted some routines to use the new cg methods
  827. Revision 1.11 2002/03/31 20:26:37 jonas
  828. + a_loadfpu_* and a_loadmm_* methods in tcg
  829. * register allocation is now handled by a class and is mostly processor
  830. independent (+rgobj.pas and i386/rgcpu.pas)
  831. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  832. * some small improvements and fixes to the optimizer
  833. * some register allocation fixes
  834. * some fpuvaroffset fixes in the unary minus node
  835. * push/popusedregisters is now called rg.save/restoreusedregisters and
  836. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  837. also better optimizable)
  838. * fixed and optimized register saving/restoring for new/dispose nodes
  839. * LOC_FPU locations now also require their "register" field to be set to
  840. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  841. - list field removed of the tnode class because it's not used currently
  842. and can cause hard-to-find bugs
  843. Revision 1.10 2002/03/04 19:10:12 peter
  844. * removed compiler warnings
  845. }