cpubase.pas 32 KB

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