cpubase.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  4. Contains the base types for the i386
  5. * This code was inspired by the NASM sources
  6. The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. {# Base unit for processor information. This unit contains
  22. enumerations of registers, opcodes, sizes, and other
  23. such things which are processor specific.
  24. }
  25. unit cpubase;
  26. {$i fpcdefs.inc}
  27. interface
  28. uses
  29. cutils,cclasses,
  30. globals,
  31. cpuinfo,
  32. aasmbase,
  33. cginfo
  34. {$ifdef delphi}
  35. ,dmisc
  36. {$endif}
  37. ;
  38. {*****************************************************************************
  39. Assembler Opcodes
  40. *****************************************************************************}
  41. type
  42. TAsmOp={$i i386op.inc}
  43. {# This should define the array of instructions as string }
  44. op2strtable=array[tasmop] of string[11];
  45. Const
  46. {# First value of opcode enumeration }
  47. firstop = low(tasmop);
  48. {# Last value of opcode enumeration }
  49. lastop = high(tasmop);
  50. {*****************************************************************************
  51. Operand Sizes
  52. *****************************************************************************}
  53. type
  54. topsize = (S_NO,
  55. S_B,S_W,S_L,S_BW,S_BL,S_WL,
  56. S_IS,S_IL,S_IQ,
  57. S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX,
  58. S_NEAR,S_FAR,S_SHORT
  59. );
  60. {*****************************************************************************
  61. Registers
  62. *****************************************************************************}
  63. {The new register coding:
  64. For now we'll use this, when the old register coding is away, we
  65. can change this into a cardinal or something so the amount of
  66. possible registers increases.
  67. High byte: Register number
  68. Low byte: Subregister
  69. Example:
  70. $0100 AL
  71. $0101 AH
  72. $0102 AX
  73. $0103 EAX
  74. $0104 RAX
  75. $0201 BL
  76. $0203 EBX}
  77. {Super register numbers:}
  78. const RS_SPECIAL = $00; {Special register}
  79. RS_EAX = $01; {EAX}
  80. RS_EBX = $02; {EBX}
  81. RS_ECX = $03; {ECX}
  82. RS_EDX = $04; {EDX}
  83. RS_ESI = $05; {ESI}
  84. RS_EDI = $06; {EDI}
  85. RS_EBP = $07; {EBP}
  86. RS_ESP = $08; {ESP}
  87. RS_R8 = $09; {R8}
  88. RS_R9 = $0a; {R9}
  89. RS_R10 = $0b; {R10}
  90. RS_R11 = $0c; {R11}
  91. RS_R12 = $0d; {R12}
  92. RS_R13 = $0e; {R13}
  93. RS_R14 = $0f; {R14}
  94. RS_R15 = $10; {R15}
  95. {Number of first and last superregister.}
  96. first_supreg = $01;
  97. last_supreg = $10;
  98. {Sub register numbers:}
  99. R_SUBL = $00; {Like AL}
  100. R_SUBH = $01; {Like AH}
  101. R_SUBW = $02; {Like AX}
  102. R_SUBD = $03; {Like EAX}
  103. R_SUBQ = $04; {Like RAX}
  104. {The subregister that specifies the entire register.}
  105. R_SUBWHOLE = R_SUBD; {i386}
  106. {R_SUBWHOLE = R_SUBQ;} {Hammer}
  107. {Special registers:}
  108. const NR_NO = $0000; {Invalid register}
  109. NR_CS = $0001; {CS}
  110. NR_DS = $0002; {DS}
  111. NR_ES = $0003; {ES}
  112. NR_SS = $0004; {SS}
  113. NR_FS = $0005; {FS}
  114. NR_GS = $0006; {GS}
  115. NR_RIP = $000F; {RIP}
  116. NR_DR0 = $0010; {DR0}
  117. NR_DR1 = $0011; {DR1}
  118. NR_DR2 = $0012; {DR2}
  119. NR_DR3 = $0013; {DR3}
  120. NR_DR6 = $0016; {DR6}
  121. NR_DR7 = $0017; {DR7}
  122. NR_CR0 = $0020; {CR0}
  123. NR_CR2 = $0021; {CR1}
  124. NR_CR3 = $0022; {CR2}
  125. NR_CR4 = $0023; {CR3}
  126. NR_TR3 = $0030; {R_TR3}
  127. NR_TR4 = $0031; {R_TR4}
  128. NR_TR5 = $0032; {R_TR5}
  129. NR_TR6 = $0033; {R_TR6}
  130. NR_TR7 = $0034; {R_TR7}
  131. {Normal registers.}
  132. const NR_AL = $0100; {AL}
  133. NR_AH = $0101; {AH}
  134. NR_AX = $0102; {AX}
  135. NR_EAX = $0103; {EAX}
  136. NR_RAX = $0104; {RAX}
  137. NR_BL = $0200; {BL}
  138. NR_BH = $0201; {BH}
  139. NR_BX = $0202; {BX}
  140. NR_EBX = $0203; {EBX}
  141. NR_RBX = $0204; {RBX}
  142. NR_CL = $0300; {CL}
  143. NR_CH = $0301; {CH}
  144. NR_CX = $0302; {CX}
  145. NR_ECX = $0303; {ECX}
  146. NR_RCX = $0304; {RCX}
  147. NR_DL = $0400; {DL}
  148. NR_DH = $0401; {DH}
  149. NR_DX = $0402; {DX}
  150. NR_EDX = $0403; {EDX}
  151. NR_RDX = $0404; {RDX}
  152. NR_SIL = $0500; {SIL}
  153. NR_SI = $0502; {SI}
  154. NR_ESI = $0503; {ESI}
  155. NR_RSI = $0504; {RSI}
  156. NR_DIL = $0600; {DIL}
  157. NR_DI = $0602; {DI}
  158. NR_EDI = $0603; {EDI}
  159. NR_RDI = $0604; {RDI}
  160. NR_BPL = $0700; {BPL}
  161. NR_BP = $0702; {BP}
  162. NR_EBP = $0703; {EBP}
  163. NR_RBP = $0704; {RBP}
  164. NR_SPL = $0800; {SPL}
  165. NR_SP = $0802; {SP}
  166. NR_ESP = $0803; {ESP}
  167. NR_RSP = $0804; {RSP}
  168. NR_R8L = $0900; {R8L}
  169. NR_R8W = $0902; {R8W}
  170. NR_R8D = $0903; {R8D}
  171. NR_R9L = $0a00; {R9D}
  172. NR_R9W = $0a02; {R9W}
  173. NR_R9D = $0a03; {R9D}
  174. NR_R10L = $0b00; {R10L}
  175. NR_R10W = $0b02; {R10W}
  176. NR_R10D = $0b03; {R10D}
  177. NR_R11L = $0c00; {R11L}
  178. NR_R11W = $0c02; {R11W}
  179. NR_R11D = $0c03; {R11D}
  180. NR_R12L = $0d00; {R12L}
  181. NR_R12W = $0d02; {R12W}
  182. NR_R12D = $0d03; {R12D}
  183. NR_R13L = $0e00; {R13L}
  184. NR_R13W = $0e02; {R13W}
  185. NR_R13D = $0e03; {R13D}
  186. NR_R14L = $0f00; {R14L}
  187. NR_R14W = $0f02; {R14W}
  188. NR_R14D = $0f03; {R14D}
  189. NR_R15L = $1000; {R15L}
  190. NR_R15W = $1002; {R15W}
  191. NR_R15D = $1003; {R15D}
  192. type
  193. {# Enumeration for all possible registers for cpu. It
  194. is to note that all registers of the same type
  195. (for example all FPU registers), should be grouped
  196. together.
  197. }
  198. { don't change the order }
  199. { it's used by the register size conversions }
  200. {$packenum 1}
  201. Toldregister = (R_NO,
  202. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  203. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  204. R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_BH,R_DH,
  205. R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
  206. R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
  207. R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
  208. R_CR0,R_CR2,R_CR3,R_CR4,
  209. R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
  210. R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
  211. R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7,
  212. R_INTREGISTER,R_FLOATREGISTER,R_MMXREGISTER,R_KNIREGISTER
  213. );
  214. type Tnewregister=word;
  215. Tregister = packed record
  216. enum:Toldregister;
  217. number:Tnewregister; {This is a word for now, change to cardinal
  218. when the old register coding is away.}
  219. end;
  220. Tsuperregister=byte;
  221. Tsubregister=byte;
  222. {$packenum normal}
  223. { A type to store register locations for 64 Bit values. }
  224. tregister64 = packed record
  225. reglo,reghi : tregister;
  226. end;
  227. { alias for compact code }
  228. treg64 = tregister64;
  229. {# Set type definition for registers }
  230. tregisterset = set of Toldregister;
  231. Tsupregset = set of Tsuperregister;
  232. const
  233. {# First register in the tregister enumeration }
  234. firstreg = low(Toldregister);
  235. {# Last register in the tregister enumeration }
  236. lastreg = R_XMM7;
  237. firstsreg = R_CS;
  238. lastsreg = R_GS;
  239. nfirstsreg = NR_CS;
  240. nlastsreg = NR_GS;
  241. regset8bit : tregisterset = [R_AL..R_DH];
  242. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  243. regset32bit : tregisterset = [R_EAX..R_EDI];
  244. { Convert reg to opsize }
  245. reg2opsize : array[firstreg..lastreg] of topsize = (S_NO,
  246. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  247. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  248. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  249. S_W,S_W,S_W,S_W,S_W,S_W,
  250. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  251. S_L,S_L,S_L,S_L,S_L,S_L,
  252. S_L,S_L,S_L,S_L,
  253. S_L,S_L,S_L,S_L,S_L,
  254. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  255. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  256. );
  257. {Converts subregister number to opsize}
  258. subreg2opsize:array[0..4] of Topsize = (S_B,S_B,S_W,S_L,S_D);
  259. {Converts subregister number to cgsize}
  260. { subreg2cgsize:array[0..4] of Tcgsize = (OS_8,OS_8,OS_16,OS_32);}
  261. {# Standard opcode string table (for each tasmop enumeration). The
  262. opcode strings should conform to the names as defined by the
  263. processor manufacturer.
  264. }
  265. std_op2str:op2strtable={$i i386int.inc}
  266. type
  267. {# Type definition for the array of string of register names }
  268. reg2strtable = array[firstreg..lastreg] of string[6];
  269. regname2regnumrec = record
  270. name:string[6];
  271. number:Tnewregister;
  272. end;
  273. const
  274. {# Standard register table (for each tregister enumeration). The
  275. register strings should conform to the the names as defined
  276. by the processor manufacturer
  277. }
  278. std_reg2str : reg2strtable = ('',
  279. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  280. 'ax','cx','dx','bx','sp','bp','si','di',
  281. 'al','cl','dl','bl','ah','ch','bh','dh',
  282. 'cs','ds','es','ss','fs','gs',
  283. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  284. 'dr0','dr1','dr2','dr3','dr6','dr7',
  285. 'cr0','cr2','cr3','cr4',
  286. 'tr3','tr4','tr5','tr6','tr7',
  287. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  288. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  289. );
  290. {*****************************************************************************
  291. Conditions
  292. *****************************************************************************}
  293. type
  294. TAsmCond=(C_None,
  295. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  296. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  297. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  298. );
  299. const
  300. cond2str:array[TAsmCond] of string[3]=('',
  301. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  302. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  303. 'ns','nz','o','p','pe','po','s','z'
  304. );
  305. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  306. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  307. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  308. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  309. );
  310. {*****************************************************************************
  311. Flags
  312. *****************************************************************************}
  313. type
  314. 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);
  315. {*****************************************************************************
  316. Reference
  317. *****************************************************************************}
  318. type
  319. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  320. { reference record }
  321. preference = ^treference;
  322. treference = packed record
  323. segment,
  324. base,
  325. index : tregister;
  326. scalefactor : byte;
  327. offset : longint;
  328. symbol : tasmsymbol;
  329. offsetfixup : longint;
  330. options : trefoptions;
  331. end;
  332. { reference record }
  333. pparareference = ^tparareference;
  334. tparareference = packed record
  335. index : tregister;
  336. offset : longint;
  337. end;
  338. {*****************************************************************************
  339. Operands
  340. *****************************************************************************}
  341. { Types of operand }
  342. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  343. toper=record
  344. ot : longint;
  345. case typ : toptype of
  346. top_none : ();
  347. top_reg : (reg:tregister);
  348. top_ref : (ref:preference);
  349. top_const : (val:aword);
  350. top_symbol : (sym:tasmsymbol;symofs:longint);
  351. end;
  352. {*****************************************************************************
  353. Generic Location
  354. *****************************************************************************}
  355. type
  356. TLoc=(
  357. LOC_INVALID, { added for tracking problems}
  358. LOC_CONSTANT, { constant value }
  359. LOC_JUMP, { boolean results only, jump to false or true label }
  360. LOC_FLAGS, { boolean results only, flags are set }
  361. LOC_CREFERENCE, { in memory constant value reference (cannot change) }
  362. LOC_REFERENCE, { in memory value }
  363. LOC_REGISTER, { in a processor register }
  364. LOC_CREGISTER, { Constant register which shouldn't be modified }
  365. LOC_FPUREGISTER, { FPU stack }
  366. LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
  367. LOC_MMXREGISTER, { MMX register }
  368. LOC_CMMXREGISTER, { MMX register variable }
  369. LOC_SSEREGISTER,
  370. LOC_CSSEREGISTER
  371. );
  372. { tparamlocation describes where a parameter for a procedure is stored.
  373. References are given from the caller's point of view. The usual
  374. TLocation isn't used, because contains a lot of unnessary fields.
  375. }
  376. tparalocation = packed record
  377. size : TCGSize;
  378. loc : TLoc;
  379. sp_fixup : longint;
  380. case TLoc of
  381. LOC_REFERENCE : (reference : tparareference);
  382. { segment in reference at the same place as in loc_register }
  383. LOC_REGISTER,LOC_CREGISTER : (
  384. case longint of
  385. 1 : (register,registerhigh : tregister);
  386. { overlay a registerlow }
  387. 2 : (registerlow : tregister);
  388. { overlay a 64 Bit register type }
  389. 3 : (reg64 : tregister64);
  390. 4 : (register64 : tregister64);
  391. );
  392. { it's only for better handling }
  393. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  394. end;
  395. tlocation = packed record
  396. loc : TLoc;
  397. size : TCGSize;
  398. case TLoc of
  399. LOC_FLAGS : (resflags : tresflags);
  400. LOC_CONSTANT : (
  401. case longint of
  402. 1 : (value : AWord);
  403. { can't do this, this layout depends on the host cpu. Use }
  404. { lo(valueqword)/hi(valueqword) instead (JM) }
  405. { 2 : (valuelow, valuehigh:AWord); }
  406. { overlay a complete 64 Bit value }
  407. 3 : (valueqword : qword);
  408. );
  409. LOC_CREFERENCE,
  410. LOC_REFERENCE : (reference : treference);
  411. { segment in reference at the same place as in loc_register }
  412. LOC_REGISTER,LOC_CREGISTER : (
  413. case longint of
  414. 1 : (register,registerhigh,segment : tregister);
  415. { overlay a registerlow }
  416. 2 : (registerlow : tregister);
  417. { overlay a 64 Bit register type }
  418. 3 : (reg64 : tregister64);
  419. 4 : (register64 : tregister64);
  420. );
  421. { it's only for better handling }
  422. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  423. end;
  424. {*****************************************************************************
  425. Constants
  426. *****************************************************************************}
  427. const
  428. { declare aliases }
  429. LOC_MMREGISTER = LOC_SSEREGISTER;
  430. LOC_CMMREGISTER = LOC_CSSEREGISTER;
  431. max_operands = 3;
  432. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  433. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  434. {# Constant defining possibly all registers which might require saving }
  435. ALL_REGISTERS = [firstreg..lastreg];
  436. ALL_INTREGISTERS = [1..255];
  437. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  438. general_superregisters = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
  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];
  460. usableregsint = [RS_EAX,RS_EBX,RS_ECX,RS_EDX];
  461. c_countusableregsint = 4;
  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. maxaddrregs = 0;
  470. addrregs = [];
  471. usableregsaddr = [];
  472. c_countusableregsaddr = 0;
  473. firstsaveintreg = RS_EAX;
  474. lastsaveintreg = RS_EDX;
  475. firstsavefpureg = R_NO;
  476. lastsavefpureg = R_NO;
  477. firstsavemmreg = R_MM0;
  478. lastsavemmreg = R_MM7;
  479. maxvarregs = 4;
  480. varregs : array[1..maxvarregs] of Toldregister =
  481. (R_EBX,R_EDX,R_ECX,R_EAX);
  482. maxfpuvarregs = 8;
  483. {# Registers which are defined as scratch and no need to save across
  484. routine calls or in assembler blocks.
  485. }
  486. max_scratch_regs = 1;
  487. scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
  488. {*****************************************************************************
  489. GDB Information
  490. *****************************************************************************}
  491. {# Register indexes for stabs information, when some
  492. parameters or variables are stored in registers.
  493. Taken from i386.c (dbx_register_map) and i386.h
  494. (FIXED_REGISTERS) from GCC 3.x source code
  495. }
  496. stab_regindex : array[firstreg..lastreg] of shortint =
  497. (-1,
  498. 0,1,2,3,4,5,6,7,
  499. 0,1,2,3,4,5,6,7,
  500. 0,1,2,3,0,1,2,3,
  501. -1,-1,-1,-1,-1,-1,
  502. 12,12,13,14,15,16,17,18,19,
  503. -1,-1,-1,-1,-1,-1,
  504. -1,-1,-1,-1,
  505. -1,-1,-1,-1,-1,
  506. 29,30,31,32,33,34,35,36,
  507. 21,22,23,24,25,26,27,28
  508. );
  509. {*****************************************************************************
  510. Default generic sizes
  511. *****************************************************************************}
  512. {# Defines the default address size for a processor, }
  513. OS_ADDR = OS_32;
  514. {# the natural int size for a processor, }
  515. OS_INT = OS_32;
  516. {# the maximum float size for a processor, }
  517. OS_FLOAT = OS_F80;
  518. {# the size of a vector register for a processor }
  519. OS_VECTOR = OS_M64;
  520. {*****************************************************************************
  521. Generic Register names
  522. *****************************************************************************}
  523. {# Stack pointer register }
  524. stack_pointer_reg = R_ESP;
  525. NR_STACK_POINTER_REG = NR_ESP;
  526. {# Frame pointer register }
  527. frame_pointer_reg = R_EBP;
  528. NR_FRAME_POINTER_REG = NR_EBP;
  529. {# Self pointer register : contains the instance address of an
  530. object or class. }
  531. self_pointer_reg = R_ESI;
  532. RS_SELF_POINTER_REG = RS_ESI;
  533. NR_SELF_POINTER_REG = NR_ESI;
  534. {# Register for addressing absolute data in a position independant way,
  535. such as in PIC code. The exact meaning is ABI specific. For
  536. further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
  537. }
  538. pic_offset_reg = R_EBX;
  539. {# Results are returned in this register (32-bit values) }
  540. accumulator = R_EAX;
  541. RS_ACCUMULATOR = RS_EAX;
  542. NR_ACCUMULATOR = NR_EAX;
  543. {the return_result_reg, is used inside the called function to store its return
  544. value when that is a scalar value otherwise a pointer to the address of the
  545. result is placed inside it}
  546. return_result_reg = accumulator;
  547. RS_RETURN_RESULT_REG = RS_ACCUMULATOR;
  548. NR_RETURN_RESULT_REG = NR_ACCUMULATOR;
  549. {the function_result_reg contains the function result after a call to a scalar
  550. function othewise it contains a pointer to the returned result}
  551. function_result_reg = accumulator;
  552. {# Hi-Results are returned in this register (64-bit value high register) }
  553. accumulatorhigh = R_EDX;
  554. RS_ACCUMULATORHIGH = RS_EDX;
  555. NR_ACCUMULATORHIGH = NR_EDX;
  556. { WARNING: don't change to R_ST0!! See comments above implementation of }
  557. { a_loadfpu* methods in rgcpu (JM) }
  558. fpu_result_reg = R_ST;
  559. mmresultreg = R_MM0;
  560. {*****************************************************************************
  561. GCC /ABI linking information
  562. *****************************************************************************}
  563. const
  564. {# Registers which must be saved when calling a routine declared as
  565. cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
  566. saved should be the ones as defined in the target ABI and / or GCC.
  567. This value can be deduced from the CALLED_USED_REGISTERS array in the
  568. GCC source.
  569. }
  570. std_saved_registers = [R_ESI,R_EDI,R_EBX];
  571. {# Required parameter alignment when calling a routine declared as
  572. stdcall and cdecl. The alignment value should be the one defined
  573. by GCC or the target ABI.
  574. The value of this constant is equal to the constant
  575. PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
  576. }
  577. std_param_align = 4;
  578. {*****************************************************************************
  579. CPU Dependent Constants
  580. *****************************************************************************}
  581. {*****************************************************************************
  582. Helpers
  583. *****************************************************************************}
  584. procedure convert_register_to_enum(var r:Tregister);
  585. function cgsize2subreg(s:Tcgsize):Tsubregister;
  586. function is_calljmp(o:tasmop):boolean;
  587. function flags_to_cond(const f: TResFlags) : TAsmCond;
  588. implementation
  589. uses verbose;
  590. {*****************************************************************************
  591. Helpers
  592. *****************************************************************************}
  593. procedure convert_register_to_enum(var r:Tregister);
  594. begin
  595. if r.enum=R_INTREGISTER then
  596. case r.number of
  597. NR_NO: r.enum:=R_NO;
  598. NR_EAX: r.enum:=R_EAX; NR_EBX: r.enum:=R_EBX;
  599. NR_ECX: r.enum:=R_ECX; NR_EDX: r.enum:=R_EDX;
  600. NR_ESI: r.enum:=R_ESI; NR_EDI: r.enum:=R_EDI;
  601. NR_ESP: r.enum:=R_ESP; NR_EBP: r.enum:=R_EBP;
  602. NR_AX: r.enum:=R_AX; NR_BX: r.enum:=R_BX;
  603. NR_CX: r.enum:=R_CX; NR_DX: r.enum:=R_DX;
  604. NR_SI: r.enum:=R_SI; NR_DI: r.enum:=R_DI;
  605. NR_SP: r.enum:=R_SP; NR_BP: r.enum:=R_BP;
  606. NR_AL: r.enum:=R_AL; NR_BL: r.enum:=R_BL;
  607. NR_CL: r.enum:=R_CL; NR_DL: r.enum:=R_DL;
  608. NR_AH: r.enum:=R_AH; NR_BH: r.enum:=R_BH;
  609. NR_CH: r.enum:=R_CH; NR_DH: r.enum:=R_DH;
  610. NR_CS: r.enum:=R_CS; NR_DS: r.enum:=R_DS;
  611. NR_ES: r.enum:=R_ES; NR_FS: r.enum:=R_FS;
  612. NR_GS: r.enum:=R_GS; NR_SS: r.enum:=R_SS;
  613. else
  614. internalerror(200301082);
  615. end;
  616. end;
  617. function cgsize2subreg(s:Tcgsize):Tsubregister;
  618. begin
  619. case s of
  620. OS_8,OS_S8:
  621. cgsize2subreg:=R_SUBL;
  622. OS_16,OS_S16:
  623. cgsize2subreg:=R_SUBW;
  624. OS_32,OS_S32:
  625. cgsize2subreg:=R_SUBD;
  626. OS_64,OS_S64:
  627. cgsize2subreg:=R_SUBQ;
  628. else
  629. internalerror(200301231);
  630. end;
  631. end;
  632. function supreg_name(r:Tsuperregister):string;
  633. var s:string[4];
  634. const supreg_names:array[0..last_supreg] of string[4]=
  635. ('INV',
  636. 'eax','ebx','ecx','edx','esi','edi','ebp','esp',
  637. 'r8' ,'r9', 'r10','r11','r12','r13','r14','r15');
  638. begin
  639. if r in [0..last_supreg] then
  640. supreg_name:=supreg_names[r]
  641. else
  642. begin
  643. str(r,s);
  644. supreg_name:='reg'+s;
  645. end;
  646. end;
  647. function is_calljmp(o:tasmop):boolean;
  648. begin
  649. case o of
  650. A_CALL,
  651. A_JCXZ,
  652. A_JECXZ,
  653. A_JMP,
  654. A_LOOP,
  655. A_LOOPE,
  656. A_LOOPNE,
  657. A_LOOPNZ,
  658. A_LOOPZ,
  659. A_Jcc :
  660. is_calljmp:=true;
  661. else
  662. is_calljmp:=false;
  663. end;
  664. end;
  665. function flags_to_cond(const f: TResFlags) : TAsmCond;
  666. const
  667. flags_2_cond : array[TResFlags] of TAsmCond =
  668. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  669. begin
  670. result := flags_2_cond[f];
  671. end;
  672. end.
  673. {
  674. $Log$
  675. Revision 1.42 2003-02-19 22:00:15 daniel
  676. * Code generator converted to new register notation
  677. - Horribily outdated todo.txt removed
  678. Revision 1.41 2003/02/02 19:25:54 carl
  679. * Several bugfixes for m68k target (register alloc., opcode emission)
  680. + VIS target
  681. + Generic add more complete (still not verified)
  682. Revision 1.40 2003/01/13 18:37:44 daniel
  683. * Work on register conversion
  684. Revision 1.39 2003/01/09 20:41:00 daniel
  685. * Converted some code in cgx86.pas to new register numbering
  686. Revision 1.38 2003/01/09 15:49:56 daniel
  687. * Added register conversion
  688. Revision 1.37 2003/01/08 22:32:36 daniel
  689. * Added register convesrion procedure
  690. Revision 1.36 2003/01/08 18:43:57 daniel
  691. * Tregister changed into a record
  692. Revision 1.35 2003/01/05 13:36:53 florian
  693. * x86-64 compiles
  694. + very basic support for float128 type (x86-64 only)
  695. Revision 1.34 2002/11/17 18:26:16 mazen
  696. * fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg
  697. Revision 1.33 2002/11/17 17:49:08 mazen
  698. + 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
  699. Revision 1.32 2002/10/05 12:43:29 carl
  700. * fixes for Delphi 6 compilation
  701. (warning : Some features do not work under Delphi)
  702. Revision 1.31 2002/08/14 18:41:48 jonas
  703. - remove valuelow/valuehigh fields from tlocation, because they depend
  704. on the endianess of the host operating system -> difficult to get
  705. right. Use lo/hi(location.valueqword) instead (remember to use
  706. valueqword and not value!!)
  707. Revision 1.30 2002/08/13 21:40:58 florian
  708. * more fixes for ppc calling conventions
  709. Revision 1.29 2002/08/12 15:08:41 carl
  710. + stab register indexes for powerpc (moved from gdb to cpubase)
  711. + tprocessor enumeration moved to cpuinfo
  712. + linker in target_info is now a class
  713. * many many updates for m68k (will soon start to compile)
  714. - removed some ifdef or correct them for correct cpu
  715. Revision 1.28 2002/08/06 20:55:23 florian
  716. * first part of ppc calling conventions fix
  717. Revision 1.27 2002/07/25 18:01:29 carl
  718. + FPURESULTREG -> FPU_RESULT_REG
  719. Revision 1.26 2002/07/07 09:52:33 florian
  720. * powerpc target fixed, very simple units can be compiled
  721. * some basic stuff for better callparanode handling, far from being finished
  722. Revision 1.25 2002/07/01 18:46:30 peter
  723. * internal linker
  724. * reorganized aasm layer
  725. Revision 1.24 2002/07/01 16:23:55 peter
  726. * cg64 patch
  727. * basics for currency
  728. * asnode updates for class and interface (not finished)
  729. Revision 1.23 2002/05/18 13:34:22 peter
  730. * readded missing revisions
  731. Revision 1.22 2002/05/16 19:46:50 carl
  732. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  733. + try to fix temp allocation (still in ifdef)
  734. + generic constructor calls
  735. + start of tassembler / tmodulebase class cleanup
  736. Revision 1.19 2002/05/12 16:53:16 peter
  737. * moved entry and exitcode to ncgutil and cgobj
  738. * foreach gets extra argument for passing local data to the
  739. iterator function
  740. * -CR checks also class typecasts at runtime by changing them
  741. into as
  742. * fixed compiler to cycle with the -CR option
  743. * fixed stabs with elf writer, finally the global variables can
  744. be watched
  745. * removed a lot of routines from cga unit and replaced them by
  746. calls to cgobj
  747. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  748. u32bit then the other is typecasted also to u32bit without giving
  749. a rangecheck warning/error.
  750. * fixed pascal calling method with reversing also the high tree in
  751. the parast, detected by tcalcst3 test
  752. Revision 1.18 2002/04/21 15:31:40 carl
  753. - removed some other stuff to their units
  754. Revision 1.17 2002/04/20 21:37:07 carl
  755. + generic FPC_CHECKPOINTER
  756. + first parameter offset in stack now portable
  757. * rename some constants
  758. + move some cpu stuff to other units
  759. - remove unused constents
  760. * fix stacksize for some targets
  761. * fix generic size problems which depend now on EXTEND_SIZE constant
  762. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  763. Revision 1.16 2002/04/15 19:53:54 peter
  764. * fixed conflicts between the last 2 commits
  765. Revision 1.15 2002/04/15 19:44:20 peter
  766. * fixed stackcheck that would be called recursively when a stack
  767. error was found
  768. * generic changeregsize(reg,size) for i386 register resizing
  769. * removed some more routines from cga unit
  770. * fixed returnvalue handling
  771. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  772. Revision 1.14 2002/04/15 19:12:09 carl
  773. + target_info.size_of_pointer -> pointer_size
  774. + some cleanup of unused types/variables
  775. * move several constants from cpubase to their specific units
  776. (where they are used)
  777. + att_Reg2str -> gas_reg2str
  778. + int_reg2str -> std_reg2str
  779. Revision 1.13 2002/04/14 16:59:41 carl
  780. + att_reg2str -> gas_reg2str
  781. Revision 1.12 2002/04/02 17:11:34 peter
  782. * tlocation,treference update
  783. * LOC_CONSTANT added for better constant handling
  784. * secondadd splitted in multiple routines
  785. * location_force_reg added for loading a location to a register
  786. of a specified size
  787. * secondassignment parses now first the right and then the left node
  788. (this is compatible with Kylix). This saves a lot of push/pop especially
  789. with string operations
  790. * adapted some routines to use the new cg methods
  791. Revision 1.11 2002/03/31 20:26:37 jonas
  792. + a_loadfpu_* and a_loadmm_* methods in tcg
  793. * register allocation is now handled by a class and is mostly processor
  794. independent (+rgobj.pas and i386/rgcpu.pas)
  795. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  796. * some small improvements and fixes to the optimizer
  797. * some register allocation fixes
  798. * some fpuvaroffset fixes in the unary minus node
  799. * push/popusedregisters is now called rg.save/restoreusedregisters and
  800. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  801. also better optimizable)
  802. * fixed and optimized register saving/restoring for new/dispose nodes
  803. * LOC_FPU locations now also require their "register" field to be set to
  804. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  805. - list field removed of the tnode class because it's not used currently
  806. and can cause hard-to-find bugs
  807. Revision 1.10 2002/03/04 19:10:12 peter
  808. * removed compiler warnings
  809. }