cpubase.pas 34 KB

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