cpubase.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  27. interface
  28. uses
  29. globals,cutils,cclasses,aasm,cpuinfo,cginfo;
  30. const
  31. { Size of the instruction table converted by nasmconv.pas }
  32. instabentries = {$i i386nop.inc}
  33. maxinfolen = 8;
  34. { By default we want everything }
  35. {$define ATTOP}
  36. {$define INTELOP}
  37. {$define ITTABLE}
  38. { We Don't need the intel style opcodes if we don't have a intel
  39. reader or generator }
  40. {$ifdef NORA386INT}
  41. {$ifdef NOAG386NSM}
  42. {$ifdef NOAG386INT}
  43. {$undef INTELOP}
  44. {$endif}
  45. {$endif}
  46. {$endif}
  47. { We Don't need the AT&T style opcodes if we don't have a AT&T
  48. reader or generator }
  49. {$ifdef NORA386ATT}
  50. {$ifdef NOAG386ATT}
  51. {$undef ATTOP}
  52. {$ifdef NOAG386DIR}
  53. {$undef ATTREG}
  54. {$endif}
  55. {$endif}
  56. {$endif}
  57. { We need the AT&T suffix table for both asm readers and AT&T writer }
  58. {$define ATTSUF}
  59. {$ifdef NORA386INT}
  60. {$ifdef NORA386ATT}
  61. {$ifdef NOAG386ATT}
  62. {$undef ATTSUF}
  63. {$endif}
  64. {$endif}
  65. {$endif}
  66. const
  67. { Operand types }
  68. OT_NONE = $00000000;
  69. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  70. OT_BITS16 = $00000002;
  71. OT_BITS32 = $00000004;
  72. OT_BITS64 = $00000008; { FPU only }
  73. OT_BITS80 = $00000010;
  74. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  75. OT_NEAR = $00000040;
  76. OT_SHORT = $00000080;
  77. OT_SIZE_MASK = $000000FF; { all the size attributes }
  78. OT_NON_SIZE = longint(not OT_SIZE_MASK);
  79. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  80. OT_TO = $00000200; { operand is followed by a colon }
  81. { reverse effect in FADD, FSUB &c }
  82. OT_COLON = $00000400;
  83. OT_REGISTER = $00001000;
  84. OT_IMMEDIATE = $00002000;
  85. OT_IMM8 = $00002001;
  86. OT_IMM16 = $00002002;
  87. OT_IMM32 = $00002004;
  88. OT_IMM64 = $00002008;
  89. OT_IMM80 = $00002010;
  90. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  91. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  92. OT_REG8 = $00201001;
  93. OT_REG16 = $00201002;
  94. OT_REG32 = $00201004;
  95. OT_MMXREG = $00201008; { MMX registers }
  96. OT_XMMREG = $00201010; { Katmai registers }
  97. OT_MEMORY = $00204000; { register number in 'basereg' }
  98. OT_MEM8 = $00204001;
  99. OT_MEM16 = $00204002;
  100. OT_MEM32 = $00204004;
  101. OT_MEM64 = $00204008;
  102. OT_MEM80 = $00204010;
  103. OT_FPUREG = $01000000; { floating point stack registers }
  104. OT_FPU0 = $01000800; { FPU stack register zero }
  105. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  106. { a mask for the following }
  107. OT_REG_ACCUM = $00211000; { accumulator: AL, AX or EAX }
  108. OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
  109. OT_REG_AX = $00211002; { ditto }
  110. OT_REG_EAX = $00211004; { and again }
  111. OT_REG_COUNT = $00221000; { counter: CL, CX or ECX }
  112. OT_REG_CL = $00221001; { REG_COUNT | BITSxx }
  113. OT_REG_CX = $00221002; { ditto }
  114. OT_REG_ECX = $00221004; { another one }
  115. OT_REG_DX = $00241002;
  116. OT_REG_SREG = $00081002; { any segment register }
  117. OT_REG_CS = $01081002; { CS }
  118. OT_REG_DESS = $02081002; { DS, ES, SS (non-CS 86 registers) }
  119. OT_REG_FSGS = $04081002; { FS, GS (386 extended registers) }
  120. OT_REG_CDT = $00101004; { CRn, DRn and TRn }
  121. OT_REG_CREG = $08101004; { CRn }
  122. OT_REG_CR4 = $08101404; { CR4 (Pentium only) }
  123. OT_REG_DREG = $10101004; { DRn }
  124. OT_REG_TREG = $20101004; { TRn }
  125. OT_MEM_OFFS = $00604000; { special type of EA }
  126. { simple [address] offset }
  127. OT_ONENESS = $00800000; { special type of immediate operand }
  128. { so UNITY == IMMEDIATE | ONENESS }
  129. OT_UNITY = $00802000; { for shift/rotate instructions }
  130. {Instruction flags }
  131. IF_NONE = $00000000;
  132. IF_SM = $00000001; { size match first two operands }
  133. IF_SM2 = $00000002;
  134. IF_SB = $00000004; { unsized operands can't be non-byte }
  135. IF_SW = $00000008; { unsized operands can't be non-word }
  136. IF_SD = $00000010; { unsized operands can't be nondword }
  137. IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
  138. IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
  139. IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
  140. IF_ARMASK = $00000060; { mask for unsized argument spec }
  141. IF_PRIV = $00000100; { it's a privileged instruction }
  142. IF_SMM = $00000200; { it's only valid in SMM }
  143. IF_PROT = $00000400; { it's protected mode only }
  144. IF_UNDOC = $00001000; { it's an undocumented instruction }
  145. IF_FPU = $00002000; { it's an FPU instruction }
  146. IF_MMX = $00004000; { it's an MMX instruction }
  147. IF_3DNOW = $00008000; { it's a 3DNow! instruction }
  148. IF_SSE = $00010000; { it's a SSE (KNI, MMX2) instruction }
  149. IF_PMASK =
  150. longint($FF000000); { the mask for processor types }
  151. IF_PFMASK =
  152. longint($F001FF00); { the mask for disassembly "prefer" }
  153. IF_8086 = $00000000; { 8086 instruction }
  154. IF_186 = $01000000; { 186+ instruction }
  155. IF_286 = $02000000; { 286+ instruction }
  156. IF_386 = $03000000; { 386+ instruction }
  157. IF_486 = $04000000; { 486+ instruction }
  158. IF_PENT = $05000000; { Pentium instruction }
  159. IF_P6 = $06000000; { P6 instruction }
  160. IF_KATMAI = $07000000; { Katmai instructions }
  161. IF_CYRIX = $10000000; { Cyrix-specific instruction }
  162. IF_AMD = $20000000; { AMD-specific instruction }
  163. { added flags }
  164. IF_PRE = $40000000; { it's a prefix instruction }
  165. IF_PASS2 =
  166. longint($80000000); { if the instruction can change in a second pass }
  167. type
  168. TAsmOp={$i i386op.inc}
  169. {# This should define the array of instructions as string }
  170. op2strtable=array[tasmop] of string[11];
  171. Const
  172. {# First value of opcode enumeration }
  173. firstop = low(tasmop);
  174. {# Last value of opcode enumeration }
  175. lastop = high(tasmop);
  176. {*****************************************************************************
  177. Operand Sizes
  178. *****************************************************************************}
  179. type
  180. topsize = (S_NO,
  181. S_B,S_W,S_L,S_BW,S_BL,S_WL,
  182. S_IS,S_IL,S_IQ,
  183. S_FS,S_FL,S_FX,S_D,S_Q,S_FV,
  184. S_NEAR,S_FAR,S_SHORT
  185. );
  186. const
  187. { Intel style operands ! }
  188. opsize_2_type:array[0..2,topsize] of longint=(
  189. (OT_NONE,
  190. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS16,OT_BITS32,OT_BITS32,
  191. OT_BITS16,OT_BITS32,OT_BITS64,
  192. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
  193. OT_NEAR,OT_FAR,OT_SHORT
  194. ),
  195. (OT_NONE,
  196. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS8,OT_BITS8,OT_BITS16,
  197. OT_BITS16,OT_BITS32,OT_BITS64,
  198. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
  199. OT_NEAR,OT_FAR,OT_SHORT
  200. ),
  201. (OT_NONE,
  202. OT_BITS8,OT_BITS16,OT_BITS32,OT_NONE,OT_NONE,OT_NONE,
  203. OT_BITS16,OT_BITS32,OT_BITS64,
  204. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64,
  205. OT_NEAR,OT_FAR,OT_SHORT
  206. )
  207. );
  208. {*****************************************************************************
  209. Conditions
  210. *****************************************************************************}
  211. type
  212. TAsmCond=(C_None,
  213. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  214. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  215. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  216. );
  217. const
  218. cond2str:array[TAsmCond] of string[3]=('',
  219. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  220. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  221. 'ns','nz','o','p','pe','po','s','z'
  222. );
  223. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  224. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  225. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  226. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  227. );
  228. <<<<<<< cpubase.pas
  229. const
  230. CondAsmOps=3;
  231. CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
  232. A_CMOVcc, A_Jcc, A_SETcc
  233. );
  234. CondAsmOpStr:array[0..CondAsmOps-1] of string[4]=(
  235. 'CMOV','J','SET'
  236. );
  237. =======
  238. >>>>>>> 1.14
  239. {*****************************************************************************
  240. Registers
  241. *****************************************************************************}
  242. type
  243. {# Enumeration for all possible registers for cpu. It
  244. is to note that all registers of the same type
  245. (for example all FPU registers), should be grouped
  246. together.
  247. }
  248. { don't change the order }
  249. { it's used by the register size conversions }
  250. tregister = (R_NO,
  251. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  252. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  253. R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_BH,R_DH,
  254. R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
  255. R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
  256. R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
  257. R_CR0,R_CR2,R_CR3,R_CR4,
  258. R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
  259. R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
  260. R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7
  261. );
  262. {# Set type definition for registers }
  263. tregisterset = set of tregister;
  264. {# Type definition for the array of string of register nnames }
  265. reg2strtable = array[tregister] of string[6];
  266. const
  267. {# First register in the tregister enumeration }
  268. firstreg = low(tregister);
  269. {# Last register in the tregister enumeration }
  270. lastreg = high(tregister);
  271. firstsreg = R_CS;
  272. lastsreg = R_GS;
  273. regset8bit : tregisterset = [R_AL..R_DH];
  274. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  275. regset32bit : tregisterset = [R_EAX..R_EDI];
  276. <<<<<<< cpubase.pas
  277. { Convert reg to opsize }
  278. reg2opsize : array[firstreg..lastreg] of topsize = (S_NO,
  279. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  280. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  281. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  282. S_W,S_W,S_W,S_W,S_W,S_W,
  283. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  284. S_L,S_L,S_L,S_L,S_L,S_L,
  285. S_L,S_L,S_L,S_L,
  286. S_L,S_L,S_L,S_L,S_L,
  287. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  288. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  289. );
  290. =======
  291. >>>>>>> 1.14
  292. <<<<<<< cpubase.pas
  293. { Convert reg to operand type }
  294. reg2type : array[firstreg..lastreg] of longint = (OT_NONE,
  295. OT_REG_EAX,OT_REG_ECX,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,
  296. OT_REG_AX,OT_REG_CX,OT_REG_DX,OT_REG16,OT_REG16,OT_REG16,OT_REG16,OT_REG16,
  297. OT_REG_AL,OT_REG_CL,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,
  298. OT_REG_CS,OT_REG_DESS,OT_REG_DESS,OT_REG_DESS,OT_REG_FSGS,OT_REG_FSGS,
  299. OT_FPU0,OT_FPU0,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,
  300. OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,
  301. OT_REG_CREG,OT_REG_CREG,OT_REG_CREG,OT_REG_CR4,
  302. OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,
  303. OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,
  304. OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG
  305. );
  306. {$ifdef INTELOP}
  307. int_reg2str : reg2strtable = ('',
  308. =======
  309. {# Standard opcode string table (for each tasmop enumeration). The
  310. opcode strings should conform to the names as defined by the
  311. processor manufacturer.
  312. }
  313. std_op2str:op2strtable={$i i386int.inc}
  314. {# Standard register table (for each tregister enumeration). The
  315. register strings should conform to the the names as defined
  316. by the processor manufacturer
  317. }
  318. std_reg2str : reg2strtable = ('',
  319. >>>>>>> 1.14
  320. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  321. 'ax','cx','dx','bx','sp','bp','si','di',
  322. 'al','cl','dl','bl','ah','ch','bh','dh',
  323. 'cs','ds','es','ss','fs','gs',
  324. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  325. 'dr0','dr1','dr2','dr3','dr6','dr7',
  326. 'cr0','cr2','cr3','cr4',
  327. 'tr3','tr4','tr5','tr6','tr7',
  328. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  329. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  330. );
  331. {*****************************************************************************
  332. Flags
  333. *****************************************************************************}
  334. type
  335. TResFlags = (F_E,F_NE,F_G,F_L,F_GE,F_LE,F_C,F_NC,F_A,F_AE,F_B,F_BE);
  336. {*****************************************************************************
  337. Reference
  338. *****************************************************************************}
  339. type
  340. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  341. type
  342. { immediate/reference record }
  343. poperreference = ^treference;
  344. treference = packed record
  345. segment,
  346. base,
  347. index : tregister;
  348. scalefactor : byte;
  349. offset : longint;
  350. symbol : tasmsymbol;
  351. offsetfixup : longint;
  352. options : trefoptions;
  353. end;
  354. {*****************************************************************************
  355. Operands
  356. *****************************************************************************}
  357. { Types of operand }
  358. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  359. toper=record
  360. ot : longint;
  361. case typ : toptype of
  362. top_none : ();
  363. top_reg : (reg:tregister);
  364. top_ref : (ref:poperreference);
  365. top_const : (val:aword);
  366. top_symbol : (sym:tasmsymbol;symofs:longint);
  367. end;
  368. {*****************************************************************************
  369. Argument Classification
  370. *****************************************************************************}
  371. {*****************************************************************************
  372. Generic Location
  373. *****************************************************************************}
  374. type
  375. TLoc=(
  376. LOC_INVALID, { added for tracking problems}
  377. LOC_CONSTANT, { constant value }
  378. LOC_JUMP, { boolean results only, jump to false or true label }
  379. LOC_FLAGS, { boolean results only, flags are set }
  380. LOC_CREFERENCE, { in memory constant value }
  381. LOC_REFERENCE, { in memory value }
  382. LOC_REGISTER, { in a processor register }
  383. LOC_CREGISTER, { Constant register which shouldn't be modified }
  384. LOC_FPUREGISTER, { FPU stack }
  385. LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
  386. LOC_MMXREGISTER, { MMX register }
  387. LOC_CMMXREGISTER, { MMX register variable }
  388. LOC_SSEREGISTER,
  389. LOC_CSSEREGISTER
  390. );
  391. plocation = ^tlocation;
  392. tlocation = packed record
  393. loc : TLoc;
  394. size : TCGSize;
  395. case TLoc of
  396. LOC_FLAGS : (resflags : tresflags);
  397. LOC_CONSTANT : (
  398. case longint of
  399. 1 : (value : AWord);
  400. 2 : (valuelow, valuehigh:AWord);
  401. );
  402. LOC_CREFERENCE,
  403. LOC_REFERENCE : (reference : treference);
  404. { segment in reference at the same place as in loc_register }
  405. LOC_REGISTER,LOC_CREGISTER : (
  406. case longint of
  407. 1 : (register,segment,registerhigh : tregister);
  408. { overlay a registerlow }
  409. 2 : (registerlow : tregister);
  410. );
  411. { it's only for better handling }
  412. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  413. end;
  414. {*****************************************************************************
  415. Constants
  416. *****************************************************************************}
  417. const
  418. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  419. { legend: }
  420. { xxxregs = set of all possibly used registers of that type in the code }
  421. { generator }
  422. { usableregsxxx = set of all 32bit components of registers that can be }
  423. { possible allocated to a regvar or using getregisterxxx (this }
  424. { excludes registers which can be only used for parameter }
  425. { passing on ABI's that define this) }
  426. { c_countusableregsxxx = amount of registers in the usableregsxxx set }
  427. intregs = [R_EAX..R_BL];
  428. usableregsint = general_registers;
  429. c_countusableregsint = 4;
  430. fpuregs = [R_ST0..R_ST7];
  431. usableregsfpu = [];
  432. c_countusableregsfpu = 0;
  433. mmregs = [R_MM0..R_MM7];
  434. usableregsmm = [R_MM0..R_MM7];
  435. c_countusableregsmm = 8;
  436. firstsaveintreg = R_EAX;
  437. lastsaveintreg = R_EBX;
  438. firstsavefpureg = R_NO;
  439. lastsavefpureg = R_NO;
  440. firstsavemmreg = R_MM0;
  441. lastsavemmreg = R_MM7;
  442. ALL_REGISTERS = [firstreg..lastreg];
  443. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  444. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  445. registers_saved_on_cdecl = [R_ESI,R_EDI,R_EBX];
  446. { generic register names }
  447. stack_pointer = R_ESP;
  448. frame_pointer = R_EBP;
  449. self_pointer = R_ESI;
  450. accumulator = R_EAX;
  451. accumulatorhigh = R_EDX;
  452. { WARNING: don't change to R_ST0!! See comments above implementation of }
  453. { a_loadfpu* methods in rgcpu (JM) }
  454. fpuresultreg = R_ST;
  455. mmresultreg = R_MM0;
  456. { the register where the vmt offset is passed to the destructor }
  457. { helper routine }
  458. vmt_offset_reg = R_EDI;
  459. scratch_regs : array[1..1] of tregister = (R_EDI);
  460. { low and high of the available maximum width integer general purpose }
  461. { registers }
  462. LoGPReg = R_EAX;
  463. HiGPReg = R_EDI;
  464. { low and high of every possible width general purpose register (same as }
  465. { above on most architctures apart from the 80x86) }
  466. LoReg = R_EAX;
  467. HiReg = R_BL;
  468. { sizes }
  469. pointer_size = 4;
  470. extended_size = 10;
  471. mmreg_size = 8;
  472. <<<<<<< cpubase.pas
  473. sizepostfix_pointer = S_L;
  474. {*****************************************************************************
  475. Instruction table
  476. *****************************************************************************}
  477. =======
  478. >>>>>>> 1.14
  479. <<<<<<< cpubase.pas
  480. {$ifndef NOAG386BIN}
  481. type
  482. tinsentry=packed record
  483. opcode : tasmop;
  484. ops : byte;
  485. optypes : array[0..2] of longint;
  486. code : array[0..maxinfolen] of char;
  487. flags : longint;
  488. end;
  489. pinsentry=^tinsentry;
  490. =======
  491. >>>>>>> 1.14
  492. <<<<<<< cpubase.pas
  493. TInsTabCache=array[TasmOp] of longint;
  494. PInsTabCache=^TInsTabCache;
  495. =======
  496. >>>>>>> 1.14
  497. <<<<<<< cpubase.pas
  498. const
  499. InsTab:array[0..instabentries-1] of TInsEntry=
  500. {$i i386tab.inc}
  501. var
  502. InsTabCache : PInsTabCache;
  503. {$endif NOAG386BIN}
  504. =======
  505. procedure InitCpu;
  506. procedure DoneCpu;
  507. >>>>>>> 1.14
  508. {*****************************************************************************
  509. Opcode propeties (needed for optimizer)
  510. *****************************************************************************}
  511. {$ifndef NOOPT}
  512. Type
  513. {What an instruction can change}
  514. TInsChange = (Ch_None,
  515. {Read from a register}
  516. Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
  517. {write from a register}
  518. Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
  519. {read and write from/to a register}
  520. Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
  521. {modify the contents of a register with the purpose of using
  522. this changed content afterwards (add/sub/..., but e.g. not rep
  523. or movsd)}
  524. Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
  525. Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
  526. Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
  527. Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
  528. Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
  529. Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
  530. Ch_WMemEDI,
  531. Ch_All
  532. );
  533. const
  534. MaxCh = 3; { Max things a instruction can change }
  535. type
  536. TInsProp = packed record
  537. Ch : Array[1..MaxCh] of TInsChange;
  538. end;
  539. const
  540. InsProp : array[tasmop] of TInsProp =
  541. {$i i386prop.inc}
  542. {$endif NOOPT}
  543. {*****************************************************************************
  544. Helpers
  545. *****************************************************************************}
  546. const
  547. maxvarregs = 4;
  548. varregs : array[1..maxvarregs] of tregister =
  549. (R_EBX,R_EDX,R_ECX,R_EAX);
  550. maxfpuvarregs = 8;
  551. max_operands = 3;
  552. maxintregs = maxvarregs;
  553. maxfpuregs = maxfpuvarregs;
  554. <<<<<<< cpubase.pas
  555. function imm_2_type(l:longint):longint;
  556. =======
  557. { the following functions allow to convert registers }
  558. { for example reg8toreg32(R_AL) returns R_EAX }
  559. { for example reg16toreg32(R_AL) gives an undefined }
  560. { result }
  561. { these functions expects that the turn of }
  562. { tregister isn't changed }
  563. function reg8toreg16(reg : tregister) : tregister;
  564. function reg8toreg32(reg : tregister) : tregister;
  565. function reg16toreg8(reg : tregister) : tregister;
  566. function reg32toreg8(reg : tregister) : tregister;
  567. function reg32toreg16(reg : tregister) : tregister;
  568. function reg16toreg32(reg : tregister) : tregister;
  569. { these procedures must be defined by all target cpus }
  570. function regtoreg8(reg : tregister) : tregister;
  571. function regtoreg16(reg : tregister) : tregister;
  572. function regtoreg32(reg : tregister) : tregister;
  573. >>>>>>> 1.14
  574. function changeregsize(r:tregister;size:topsize):tregister;
  575. function reg2str(r : tregister) : string;
  576. function is_calljmp(o:tasmop):boolean;
  577. procedure inverse_flags(var f: TResFlags);
  578. function flags_to_cond(const f: TResFlags) : TAsmCond;
  579. implementation
  580. uses
  581. {$ifdef heaptrc}
  582. ppheap,
  583. {$endif heaptrc}
  584. verbose;
  585. const
  586. reg2reg32 : array[tregister] of tregister = (R_NO,
  587. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  588. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  589. R_EAX,R_ECX,R_EDX,R_EBX,R_NO,R_NO,R_NO,R_NO,
  590. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  591. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  592. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  593. R_NO,R_NO,R_NO,R_NO,
  594. R_NO,R_NO,R_NO,R_NO,R_NO,
  595. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  596. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO
  597. );
  598. reg2reg16 : array[tregister] of tregister = (R_NO,
  599. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  600. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  601. R_AX,R_CX,R_DX,R_BX,R_NO,R_NO,R_NO,R_NO,
  602. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  603. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  604. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  605. R_NO,R_NO,R_NO,R_NO,
  606. R_NO,R_NO,R_NO,R_NO,R_NO,
  607. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  608. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO
  609. );
  610. reg2reg8 : array[tregister] of tregister = (R_NO,
  611. R_AL,R_CL,R_DL,R_BL,R_NO,R_NO,R_NO,R_NO,
  612. R_AL,R_CL,R_DL,R_BL,R_NO,R_NO,R_NO,R_NO,
  613. R_AL,R_CL,R_DL,R_BL,R_NO,R_NO,R_NO,R_NO,
  614. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  615. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  616. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  617. R_NO,R_NO,R_NO,R_NO,
  618. R_NO,R_NO,R_NO,R_NO,R_NO,
  619. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  620. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO
  621. );
  622. {*****************************************************************************
  623. Helpers
  624. *****************************************************************************}
  625. function is_calljmp(o:tasmop):boolean;
  626. begin
  627. case o of
  628. A_CALL,
  629. A_JCXZ,
  630. A_JECXZ,
  631. A_JMP,
  632. A_LOOP,
  633. A_LOOPE,
  634. A_LOOPNE,
  635. A_LOOPNZ,
  636. A_LOOPZ,
  637. A_Jcc :
  638. is_calljmp:=true;
  639. else
  640. is_calljmp:=false;
  641. end;
  642. end;
  643. function changeregsize(r:tregister;size:topsize):tregister;
  644. var
  645. reg : tregister;
  646. begin
  647. case size of
  648. S_B :
  649. reg:=reg2reg8[r];
  650. S_W :
  651. reg:=reg2reg16[r];
  652. S_L :
  653. reg:=reg2reg32[r];
  654. else
  655. internalerror(200204101);
  656. end;
  657. if reg=R_NO then
  658. internalerror(200204102);
  659. changeregsize:=reg;
  660. end;
  661. procedure inverse_flags(var f: TResFlags);
  662. const
  663. flagsinvers : array[F_E..F_BE] of tresflags =
  664. (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
  665. F_BE,F_B,F_AE,F_A);
  666. begin
  667. f := flagsinvers[f];
  668. end;
  669. function flags_to_cond(const f: TResFlags) : TAsmCond;
  670. const
  671. flags_2_cond : array[TResFlags] of TAsmCond =
  672. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  673. begin
  674. result := flags_2_cond[f];
  675. end;
  676. procedure InitCpu;
  677. begin
  678. end;
  679. procedure DoneCpu;
  680. begin
  681. end;
  682. end.
  683. {
  684. $Log$
  685. Revision 1.15 2002-04-15 19:44:20 peter
  686. * fixed stackcheck that would be called recursively when a stack
  687. error was found
  688. * generic changeregsize(reg,size) for i386 register resizing
  689. * removed some more routines from cga unit
  690. * fixed returnvalue handling
  691. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  692. Revision 1.14 2002/04/15 19:12:09 carl
  693. + target_info.size_of_pointer -> pointer_size
  694. + some cleanup of unused types/variables
  695. * move several constants from cpubase to their specific units
  696. (where they are used)
  697. + att_Reg2str -> gas_reg2str
  698. + int_reg2str -> std_reg2str
  699. Revision 1.13 2002/04/14 16:59:41 carl
  700. + att_reg2str -> gas_reg2str
  701. Revision 1.12 2002/04/02 17:11:34 peter
  702. * tlocation,treference update
  703. * LOC_CONSTANT added for better constant handling
  704. * secondadd splitted in multiple routines
  705. * location_force_reg added for loading a location to a register
  706. of a specified size
  707. * secondassignment parses now first the right and then the left node
  708. (this is compatible with Kylix). This saves a lot of push/pop especially
  709. with string operations
  710. * adapted some routines to use the new cg methods
  711. Revision 1.11 2002/03/31 20:26:37 jonas
  712. + a_loadfpu_* and a_loadmm_* methods in tcg
  713. * register allocation is now handled by a class and is mostly processor
  714. independent (+rgobj.pas and i386/rgcpu.pas)
  715. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  716. * some small improvements and fixes to the optimizer
  717. * some register allocation fixes
  718. * some fpuvaroffset fixes in the unary minus node
  719. * push/popusedregisters is now called rg.save/restoreusedregisters and
  720. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  721. also better optimizable)
  722. * fixed and optimized register saving/restoring for new/dispose nodes
  723. * LOC_FPU locations now also require their "register" field to be set to
  724. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  725. - list field removed of the tnode class because it's not used currently
  726. and can cause hard-to-find bugs
  727. Revision 1.10 2002/03/04 19:10:12 peter
  728. * removed compiler warnings
  729. Revision 1.9 2001/12/30 17:24:46 jonas
  730. * range checking is now processor independent (part in cgobj,
  731. part in cg64f32) and should work correctly again (it needed
  732. some changes after the changes of the low and high of
  733. tordef's to int64)
  734. * maketojumpbool() is now processor independent (in ncgutil)
  735. * getregister32 is now called getregisterint
  736. Revision 1.8 2001/12/29 15:29:59 jonas
  737. * powerpc/cgcpu.pas compiles :)
  738. * several powerpc-related fixes
  739. * cpuasm unit is now based on common tainst unit
  740. + nppcmat unit for powerpc (almost complete)
  741. Revision 1.7 2001/12/06 17:57:40 florian
  742. + parasym to tparaitem added
  743. Revision 1.6 2001/09/28 20:39:33 jonas
  744. * changed all flow control structures (except for exception handling
  745. related things) to processor independent code (in new ncgflw unit)
  746. + generic cgobj unit which contains lots of code generator helpers with
  747. global "cg" class instance variable
  748. + cgcpu unit for i386 (implements processor specific routines of the above
  749. unit)
  750. * updated cgbase and cpubase for the new code generator units
  751. * include ncgflw unit in cpunode unit
  752. Revision 1.5 2001/05/18 23:01:13 peter
  753. * portable constants
  754. Revision 1.4 2001/04/13 01:22:18 peter
  755. * symtable change to classes
  756. * range check generation and errors fixed, make cycle DEBUG=1 works
  757. * memory leaks fixed
  758. Revision 1.3 2001/02/20 21:34:04 peter
  759. * iret, lret fixes
  760. Revision 1.2 2000/12/07 17:19:45 jonas
  761. * new constant handling: from now on, hex constants >$7fffffff are
  762. parsed as unsigned constants (otherwise, $80000000 got sign extended
  763. and became $ffffffff80000000), all constants in the longint range
  764. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  765. are cardinals and the rest are int64's.
  766. * added lots of longint typecast to prevent range check errors in the
  767. compiler and rtl
  768. * type casts of symbolic ordinal constants are now preserved
  769. * fixed bug where the original resulttype wasn't restored correctly
  770. after doing a 64bit rangecheck
  771. Revision 1.1 2000/10/15 09:39:37 peter
  772. * moved cpu*.pas to i386/
  773. * renamed n386 to common cpunode
  774. Revision 1.7 2000/09/26 20:06:13 florian
  775. * hmm, still a lot of work to get things compilable
  776. Revision 1.6 2000/09/24 15:06:14 peter
  777. * use defines.inc
  778. Revision 1.5 2000/08/27 16:11:50 peter
  779. * moved some util functions from globals,cobjects to cutils
  780. * splitted files into finput,fmodule
  781. Revision 1.4 2000/08/05 13:25:06 peter
  782. * packenum 1 fixes (merged)
  783. Revision 1.3 2000/07/14 05:11:48 michael
  784. + Patch to 1.1
  785. Revision 1.2 2000/07/13 11:32:39 michael
  786. + removed logs
  787. }