cpubase.pas 36 KB

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