cpubase.pas 33 KB

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