cpubase.pas 31 KB

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