cpubase.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  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. unit cpubase;
  22. {$ifdef newOptimizations}
  23. {$define foropt}
  24. {$define replacereg}
  25. {$define arithopt}
  26. {$define foldarithops}
  27. {$endif newOptimizations}
  28. interface
  29. {$ifdef TP}
  30. {$L-,Y-}
  31. {$endif}
  32. uses
  33. globals,strings,cobjects,aasm;
  34. const
  35. { Size of the instruction table converted by nasmconv.pas }
  36. instabentries = 1309;
  37. maxinfolen = 8;
  38. { By default we want everything }
  39. {$define ATTOP}
  40. {$define ATTREG}
  41. {$define INTELOP}
  42. {$define ITTABLE}
  43. { For TP we can't use asmdebug due the table sizes }
  44. {$ifndef TP}
  45. {$define ASMDEBUG}
  46. {$endif}
  47. { We Don't need the intel style opcodes if we don't have a intel
  48. reader or generator }
  49. {$ifndef ASMDEBUG}
  50. {$ifdef NORA386INT}
  51. {$ifdef NOAG386NSM}
  52. {$ifdef NOAG386INT}
  53. {$undef INTELOP}
  54. {$endif}
  55. {$endif}
  56. {$endif}
  57. {$endif}
  58. { We Don't need the AT&T style opcodes if we don't have a AT&T
  59. reader or generator }
  60. {$ifdef NORA386ATT}
  61. {$ifdef NOAG386ATT}
  62. {$undef ATTOP}
  63. {$ifdef NOAG386DIR}
  64. {$undef ATTREG}
  65. {$endif}
  66. {$endif}
  67. {$endif}
  68. const
  69. { Operand types }
  70. OT_NONE = $00000000;
  71. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  72. OT_BITS16 = $00000002;
  73. OT_BITS32 = $00000004;
  74. OT_BITS64 = $00000008; { FPU only }
  75. OT_BITS80 = $00000010;
  76. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  77. OT_NEAR = $00000040;
  78. OT_SHORT = $00000080;
  79. OT_SIZE_MASK = $000000FF; { all the size attributes }
  80. OT_NON_SIZE = not OT_SIZE_MASK;
  81. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  82. OT_TO = $00000200; { operand is followed by a colon }
  83. { reverse effect in FADD, FSUB &c }
  84. OT_COLON = $00000400;
  85. OT_REGISTER = $00001000;
  86. OT_IMMEDIATE = $00002000;
  87. OT_IMM8 = $00002001;
  88. OT_IMM16 = $00002002;
  89. OT_IMM32 = $00002004;
  90. OT_IMM64 = $00002008;
  91. OT_IMM80 = $00002010;
  92. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  93. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  94. OT_REG8 = $00201001;
  95. OT_REG16 = $00201002;
  96. OT_REG32 = $00201004;
  97. OT_MMXREG = $00201008; { MMX registers }
  98. OT_XMMREG = $00201010; { Katmai registers }
  99. OT_MEMORY = $00204000; { register number in 'basereg' }
  100. OT_MEM8 = $00204001;
  101. OT_MEM16 = $00204002;
  102. OT_MEM32 = $00204004;
  103. OT_MEM64 = $00204008;
  104. OT_MEM80 = $00204010;
  105. OT_FPUREG = $01000000; { floating point stack registers }
  106. OT_FPU0 = $01000800; { FPU stack register zero }
  107. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  108. { a mask for the following }
  109. OT_REG_ACCUM = $00211000; { accumulator: AL, AX or EAX }
  110. OT_REG_AL = $00211001; { REG_ACCUM | BITSxx }
  111. OT_REG_AX = $00211002; { ditto }
  112. OT_REG_EAX = $00211004; { and again }
  113. OT_REG_COUNT = $00221000; { counter: CL, CX or ECX }
  114. OT_REG_CL = $00221001; { REG_COUNT | BITSxx }
  115. OT_REG_CX = $00221002; { ditto }
  116. OT_REG_ECX = $00221004; { another one }
  117. OT_REG_DX = $00241002;
  118. OT_REG_SREG = $00081002; { any segment register }
  119. OT_REG_CS = $01081002; { CS }
  120. OT_REG_DESS = $02081002; { DS, ES, SS (non-CS 86 registers) }
  121. OT_REG_FSGS = $04081002; { FS, GS (386 extended registers) }
  122. OT_REG_CDT = $00101004; { CRn, DRn and TRn }
  123. OT_REG_CREG = $08101004; { CRn }
  124. OT_REG_CR4 = $08101404; { CR4 (Pentium only) }
  125. OT_REG_DREG = $10101004; { DRn }
  126. OT_REG_TREG = $20101004; { TRn }
  127. OT_MEM_OFFS = $00604000; { special type of EA }
  128. { simple [address] offset }
  129. OT_ONENESS = $00800000; { special type of immediate operand }
  130. { so UNITY == IMMEDIATE | ONENESS }
  131. OT_UNITY = $00802000; { for shift/rotate instructions }
  132. {Instruction flags }
  133. IF_NONE = $00000000;
  134. IF_SM = $00000001; { size match first two operands }
  135. IF_SM2 = $00000002;
  136. IF_SB = $00000004; { unsized operands can't be non-byte }
  137. IF_SW = $00000008; { unsized operands can't be non-word }
  138. IF_SD = $00000010; { unsized operands can't be nondword }
  139. IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
  140. IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
  141. IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
  142. IF_ARMASK = $00000060; { mask for unsized argument spec }
  143. IF_PRIV = $00000100; { it's a privileged instruction }
  144. IF_SMM = $00000200; { it's only valid in SMM }
  145. IF_PROT = $00000400; { it's protected mode only }
  146. IF_UNDOC = $00001000; { it's an undocumented instruction }
  147. IF_FPU = $00002000; { it's an FPU instruction }
  148. IF_MMX = $00004000; { it's an MMX instruction }
  149. IF_3DNOW = $00008000; { it's a 3DNow! instruction }
  150. IF_SSE = $00010000; { it's a SSE (KNI, MMX2) instruction }
  151. IF_PMASK = $FF000000; { the mask for processor types }
  152. IF_PFMASK = $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 = $80000000; { if the instruction can change in a second pass }
  166. type
  167. TAsmOp=
  168. {$i i386op.inc}
  169. op2strtable=array[tasmop] of string[10];
  170. const
  171. firstop = low(tasmop);
  172. lastop = high(tasmop);
  173. AsmPrefixes = 6;
  174. AsmPrefix : array[0..AsmPrefixes-1] of TasmOP =(
  175. A_LOCK,A_REP,A_REPE,A_REPNE,A_REPNZ,A_REPZ
  176. );
  177. AsmOverrides = 6;
  178. AsmOverride : array[0..AsmOverrides-1] of TasmOP =(
  179. A_CS,A_ES,A_DS,A_FS,A_GS,A_SS
  180. );
  181. {$ifdef INTELOP}
  182. int_op2str:op2strtable=
  183. {$i i386int.inc}
  184. {$endif INTELOP}
  185. {$ifdef ATTOP}
  186. att_op2str:op2strtable=
  187. {$i i386att.inc}
  188. att_needsuffix:array[tasmop] of boolean=
  189. {$i i386atts.inc}
  190. {$endif ATTOP}
  191. {*****************************************************************************
  192. Operand Sizes
  193. *****************************************************************************}
  194. type
  195. topsize = (S_NO,
  196. S_B,S_W,S_L,S_BW,S_BL,S_WL,
  197. S_IS,S_IL,S_IQ,
  198. S_FS,S_FL,S_FX,S_D,S_Q,S_FV
  199. );
  200. const
  201. { Intel style operands ! }
  202. opsize_2_type:array[0..2,topsize] of longint=(
  203. (OT_NONE,
  204. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS16,OT_BITS32,OT_BITS32,
  205. OT_BITS16,OT_BITS32,OT_BITS64,
  206. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64
  207. ),
  208. (OT_NONE,
  209. OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS8,OT_BITS8,OT_BITS16,
  210. OT_BITS16,OT_BITS32,OT_BITS64,
  211. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64
  212. ),
  213. (OT_NONE,
  214. OT_BITS8,OT_BITS16,OT_BITS32,OT_NONE,OT_NONE,OT_NONE,
  215. OT_BITS16,OT_BITS32,OT_BITS64,
  216. OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_BITS64,OT_BITS64
  217. )
  218. );
  219. {$ifdef ATTOP}
  220. att_opsize2str : array[topsize] of string[2] = ('',
  221. 'b','w','l','bw','bl','wl',
  222. 's','l','q',
  223. 's','l','t','d','q','v'
  224. );
  225. {$endif}
  226. {*****************************************************************************
  227. Conditions
  228. *****************************************************************************}
  229. type
  230. TAsmCond=(C_None,
  231. C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
  232. C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
  233. C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
  234. );
  235. const
  236. cond2str:array[TAsmCond] of string[3]=('',
  237. 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
  238. 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
  239. 'ns','nz','o','p','pe','po','s','z'
  240. );
  241. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  242. C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
  243. C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
  244. C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
  245. );
  246. const
  247. CondAsmOps=3;
  248. CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
  249. A_CMOVcc, A_Jcc, A_SETcc
  250. );
  251. CondAsmOpStr:array[0..CondAsmOps-1] of string[4]=(
  252. 'CMOV','J','SET'
  253. );
  254. {*****************************************************************************
  255. Registers
  256. *****************************************************************************}
  257. type
  258. { enumeration for registers, don't change the order }
  259. { it's used by the register size conversions }
  260. tregister = (R_NO,
  261. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  262. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  263. R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_BH,R_DH,
  264. R_CS,R_DS,R_ES,R_SS,R_FS,R_GS,
  265. R_ST,R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7,
  266. R_DR0,R_DR1,R_DR2,R_DR3,R_DR6,R_DR7,
  267. R_CR0,R_CR2,R_CR3,R_CR4,
  268. R_TR3,R_TR4,R_TR5,R_TR6,R_TR7,
  269. R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7,
  270. R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7
  271. );
  272. tregisterset = set of tregister;
  273. reg2strtable = array[tregister] of string[6];
  274. const
  275. firstreg = low(tregister);
  276. lastreg = high(tregister);
  277. firstsreg = R_CS;
  278. lastsreg = R_GS;
  279. regset8bit : tregisterset = [R_AL..R_DH];
  280. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  281. regset32bit : tregisterset = [R_EAX..R_EDI];
  282. { Convert reg to opsize }
  283. reg_2_opsize:array[firstreg..lastreg] of topsize = (S_NO,
  284. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  285. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  286. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  287. S_W,S_W,S_W,S_W,S_W,S_W,
  288. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  289. S_L,S_L,S_L,S_L,S_L,S_L,
  290. S_L,S_L,S_L,S_L,
  291. S_L,S_L,S_L,S_L,S_L,
  292. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  293. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  294. );
  295. { Convert reg to operand type }
  296. reg_2_type:array[firstreg..lastreg] of longint = (OT_NONE,
  297. OT_REG_EAX,OT_REG_ECX,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,OT_REG32,
  298. OT_REG_AX,OT_REG_CX,OT_REG_DX,OT_REG16,OT_REG16,OT_REG16,OT_REG16,OT_REG16,
  299. OT_REG_AL,OT_REG_CL,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,OT_REG8,
  300. OT_REG_CS,OT_REG_DESS,OT_REG_DESS,OT_REG_DESS,OT_REG_FSGS,OT_REG_FSGS,
  301. OT_FPU0,OT_FPU0,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,OT_FPUREG,
  302. OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,OT_REG_DREG,
  303. OT_REG_CREG,OT_REG_CREG,OT_REG_CREG,OT_REG_CR4,
  304. OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,OT_REG_TREG,
  305. OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,OT_MMXREG,
  306. OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG,OT_XMMREG
  307. );
  308. {$ifdef INTELOP}
  309. int_reg2str : reg2strtable = ('',
  310. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  311. 'ax','cx','dx','bx','sp','bp','si','di',
  312. 'al','cl','dl','bl','ah','ch','bh','dh',
  313. 'cs','ds','es','ss','fs','gs',
  314. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  315. 'dr0','dr1','dr2','dr3','dr6','dr7',
  316. 'cr0','cr2','cr3','cr4',
  317. 'tr3','tr4','tr5','tr6','tr7',
  318. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  319. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  320. );
  321. int_nasmreg2str : reg2strtable = ('',
  322. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  323. 'ax','cx','dx','bx','sp','bp','si','di',
  324. 'al','cl','dl','bl','ah','ch','bh','dh',
  325. 'cs','ds','es','ss','fs','gs',
  326. 'st0','st0','st1','st2','st3','st4','st5','st6','st7',
  327. 'dr0','dr1','dr2','dr3','dr6','dr7',
  328. 'cr0','cr2','cr3','cr4',
  329. 'tr3','tr4','tr5','tr6','tr7',
  330. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  331. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  332. );
  333. {$endif}
  334. {$ifdef ATTREG}
  335. att_reg2str : reg2strtable = ('',
  336. '%eax','%ecx','%edx','%ebx','%esp','%ebp','%esi','%edi',
  337. '%ax','%cx','%dx','%bx','%sp','%bp','%si','%di',
  338. '%al','%cl','%dl','%bl','%ah','%ch','%bh','%dh',
  339. '%cs','%ds','%es','%ss','%fs','%gs',
  340. '%st','%st(0)','%st(1)','%st(2)','%st(3)','%st(4)','%st(5)','%st(6)','%st(7)',
  341. '%dr0','%dr1','%dr2','%dr3','%dr6','%dr7',
  342. '%cr0','%cr2','%cr3','%cr4',
  343. '%tr3','%tr4','%tr5','%tr6','%tr7',
  344. '%mm0','%mm1','%mm2','%mm3','%mm4','%mm5','%mm6','%mm7',
  345. '%xmm0','%xmm1','%xmm2','%xmm3','%xmm4','%xmm5','%xmm6','%xmm7'
  346. );
  347. {$endif ATTREG}
  348. {*****************************************************************************
  349. Flags
  350. *****************************************************************************}
  351. type
  352. 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);
  353. const
  354. { arrays for boolean location conversions }
  355. flag_2_cond : array[TResFlags] of TAsmCond =
  356. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  357. {*****************************************************************************
  358. Reference
  359. *****************************************************************************}
  360. type
  361. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  362. { immediate/reference record }
  363. preference = ^treference;
  364. treference = packed record
  365. is_immediate : boolean; { is this used as reference or immediate }
  366. segment,
  367. base,
  368. index : tregister;
  369. scalefactor : byte;
  370. offset : longint;
  371. symbol : pasmsymbol;
  372. offsetfixup : longint;
  373. options : trefoptions;
  374. {$ifdef newcg}
  375. alignment : byte;
  376. {$endif newcg}
  377. end;
  378. {*****************************************************************************
  379. Operands
  380. *****************************************************************************}
  381. { Types of operand }
  382. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  383. toper=record
  384. ot : longint;
  385. case typ : toptype of
  386. top_none : ();
  387. top_reg : (reg:tregister);
  388. top_ref : (ref:preference);
  389. top_const : (val:longint);
  390. top_symbol : (sym:pasmsymbol;symofs:longint);
  391. end;
  392. {*****************************************************************************
  393. Generic Location
  394. *****************************************************************************}
  395. type
  396. TLoc=(
  397. LOC_INVALID, { added for tracking problems}
  398. LOC_FPU, { FPU stack }
  399. LOC_REGISTER, { in a processor register }
  400. LOC_MEM, { in memory }
  401. LOC_REFERENCE, { like LOC_MEM, but lvalue }
  402. LOC_JUMP, { boolean results only, jump to false or true label }
  403. LOC_FLAGS, { boolean results only, flags are set }
  404. LOC_CREGISTER, { Constant register which shouldn't be modified }
  405. LOC_MMXREGISTER, { MMX register }
  406. LOC_CMMXREGISTER,{ Constant MMX register }
  407. LOC_CFPUREGISTER { if it is a FPU register variable on the fpu stack }
  408. );
  409. plocation = ^tlocation;
  410. tlocation = packed record
  411. case loc : tloc of
  412. LOC_MEM,LOC_REFERENCE : (reference : treference);
  413. LOC_FPU : ();
  414. LOC_JUMP : ();
  415. LOC_FLAGS : (resflags : tresflags);
  416. LOC_INVALID : ();
  417. { it's only for better handling }
  418. LOC_MMXREGISTER : (mmxreg : tregister);
  419. { segment in reference at the same place as in loc_register }
  420. LOC_REGISTER,LOC_CREGISTER : (
  421. case longint of
  422. 1 : (register,segment,registerhigh : tregister);
  423. { overlay a registerlow }
  424. 2 : (registerlow : tregister);
  425. );
  426. end;
  427. {*****************************************************************************
  428. Constants
  429. *****************************************************************************}
  430. const
  431. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  432. intregs = general_registers;
  433. fpuregs = [];
  434. mmregs = [R_MM0..R_MM7];
  435. registers_saved_on_cdecl = [R_ESI,R_EDI,R_EBX];
  436. { generic register names }
  437. stack_pointer = R_ESP;
  438. frame_pointer = R_EBP;
  439. self_pointer = R_ESI;
  440. accumulator = R_EAX;
  441. { the register where the vmt offset is passed to the destructor }
  442. { helper routine }
  443. vmt_offset_reg = R_EDI;
  444. scratch_regs : array[1..1] of tregister = (R_EDI);
  445. max_scratch_regs = 1;
  446. { low and high of the available maximum width integer general purpose }
  447. { registers }
  448. LoGPReg = R_EAX;
  449. HiGPReg = R_EDI;
  450. { low and high of every possible width general purpose register (same as }
  451. { above on most architctures apart from the 80x86) }
  452. LoReg = R_EAX;
  453. HiReg = R_BL;
  454. cpuflags = [];
  455. { sizes }
  456. pointersize = 4;
  457. extended_size = 10;
  458. sizepostfix_pointer = S_L;
  459. {*****************************************************************************
  460. Instruction table
  461. *****************************************************************************}
  462. {$ifndef NOAG386BIN}
  463. type
  464. tinsentry=packed record
  465. opcode : tasmop;
  466. ops : byte;
  467. optypes : array[0..2] of longint;
  468. code : array[0..maxinfolen] of char;
  469. flags : longint;
  470. end;
  471. pinsentry=^tinsentry;
  472. TInsTabCache=array[TasmOp] of longint;
  473. PInsTabCache=^TInsTabCache;
  474. const
  475. InsTab:array[0..instabentries-1] of TInsEntry=
  476. {$i i386tab.inc}
  477. var
  478. InsTabCache : PInsTabCache;
  479. {$endif NOAG386BIN}
  480. {*****************************************************************************
  481. Opcode propeties (needed for optimizer)
  482. *****************************************************************************}
  483. {$ifndef NOOPT}
  484. Type
  485. {What an instruction can change}
  486. TInsChange = (Ch_None,
  487. {Read from a register}
  488. Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
  489. {write from a register}
  490. Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
  491. {read and write from/to a register}
  492. Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
  493. {modify the contents of a register with the purpose of using
  494. this changed content afterwards (add/sub/..., but e.g. not rep
  495. or movsd)}
  496. {$ifdef arithopt}
  497. Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
  498. {$endif arithopt}
  499. Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
  500. Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
  501. Ch_Rop1, Ch_Wop1, Ch_RWop1,
  502. Ch_Rop2, Ch_Wop2, Ch_RWop2,
  503. Ch_Rop3, Ch_WOp3, Ch_RWOp3,
  504. {$ifdef arithopt}
  505. Ch_Mop1, Ch_Mop2, Ch_Mop3,
  506. {$endif arithopt}
  507. Ch_WMemEDI,
  508. Ch_All
  509. );
  510. {$ifndef arithopt}
  511. Const
  512. Ch_MEAX = Ch_RWEAX;
  513. Ch_MECX = Ch_RWECX;
  514. Ch_MEDX = Ch_RWEDX;
  515. Ch_MEBX = Ch_RWEBX;
  516. Ch_MESP = Ch_RWESP;
  517. Ch_MEBP = Ch_RWEBP;
  518. Ch_MESI = Ch_RWESI;
  519. Ch_MEDI = Ch_RWEDI;
  520. Ch_Mop1 = Ch_RWOp1;
  521. Ch_Mop2 = Ch_RWOp2;
  522. Ch_Mop3 = Ch_RWOp3;
  523. {$endif arithopt}
  524. const
  525. MaxCh = 3; { Max things a instruction can change }
  526. type
  527. TInsProp = packed record
  528. Ch : Array[1..MaxCh] of TInsChange;
  529. end;
  530. const
  531. InsProp : array[tasmop] of TInsProp =
  532. {$i i386prop.inc}
  533. {$endif NOOPT}
  534. {*****************************************************************************
  535. Init/Done
  536. *****************************************************************************}
  537. procedure InitCpu;
  538. procedure DoneCpu;
  539. {*****************************************************************************
  540. Helpers
  541. *****************************************************************************}
  542. const
  543. maxvarregs = 4;
  544. varregs : array[1..maxvarregs] of tregister =
  545. (R_EBX,R_EDX,R_ECX,R_EAX);
  546. maxfpuvarregs = 8;
  547. max_operands = 3;
  548. function imm_2_type(l:longint):longint;
  549. { the following functions allow to convert registers }
  550. { for example reg8toreg32(R_AL) returns R_EAX }
  551. { for example reg16toreg32(R_AL) gives an undefined }
  552. { result }
  553. { these functions expects that the turn of }
  554. { tregister isn't changed }
  555. function reg8toreg16(reg : tregister) : tregister;
  556. function reg8toreg32(reg : tregister) : tregister;
  557. function reg16toreg8(reg : tregister) : tregister;
  558. function reg32toreg8(reg : tregister) : tregister;
  559. function reg32toreg16(reg : tregister) : tregister;
  560. function reg16toreg32(reg : tregister) : tregister;
  561. { these procedures must be defined by all target cpus }
  562. function regtoreg8(reg : tregister) : tregister;
  563. function regtoreg16(reg : tregister) : tregister;
  564. function regtoreg32(reg : tregister) : tregister;
  565. { can be ignored on 32 bit systems }
  566. function regtoreg64(reg : tregister) : tregister;
  567. { returns the operand prefix for a given register }
  568. function regsize(reg : tregister) : topsize;
  569. { resets all values of ref to defaults }
  570. procedure reset_reference(var ref : treference);
  571. { set mostly used values of a new reference }
  572. function new_reference(base : tregister;offset : longint) : preference;
  573. function newreference(const r : treference) : preference;
  574. procedure disposereference(var r : preference);
  575. function reg2str(r : tregister) : string;
  576. function is_calljmp(o:tasmop):boolean;
  577. implementation
  578. {$ifdef heaptrc}
  579. uses
  580. ppheap;
  581. {$endif heaptrc}
  582. {*****************************************************************************
  583. Helpers
  584. *****************************************************************************}
  585. function imm_2_type(l:longint):longint;
  586. begin
  587. if (l>=-128) and (l<=127) then
  588. imm_2_type:=OT_IMM8 or OT_SIGNED
  589. else
  590. if (l>=-255) and (l<=255) then
  591. imm_2_type:=OT_IMM8
  592. else
  593. if (l>=-32768) and (l<=32767) then
  594. imm_2_type:=OT_IMM16 or OT_SIGNED
  595. else
  596. if (l>=-65536) and (l<=65535) then
  597. imm_2_type:=OT_IMM16 or OT_SIGNED
  598. else
  599. imm_2_type:=OT_IMM32;
  600. end;
  601. function reg2str(r : tregister) : string;
  602. const
  603. a : array[R_NO..R_BL] of string[3] =
  604. ('','EAX','ECX','EDX','EBX','ESP','EBP','ESI','EDI',
  605. 'AX','CX','DX','BX','SP','BP','SI','DI',
  606. 'AL','CL','DL','BL');
  607. begin
  608. if r in [R_ST0..R_ST7] then
  609. reg2str:='ST('+tostr(longint(r)-longint(R_ST0))+')'
  610. else
  611. reg2str:=a[r];
  612. end;
  613. function is_calljmp(o:tasmop):boolean;
  614. begin
  615. case o of
  616. A_CALL,
  617. A_JCXZ,
  618. A_JECXZ,
  619. A_JMP,
  620. A_LOOP,
  621. A_LOOPE,
  622. A_LOOPNE,
  623. A_LOOPNZ,
  624. A_LOOPZ,
  625. A_Jcc :
  626. is_calljmp:=true;
  627. else
  628. is_calljmp:=false;
  629. end;
  630. end;
  631. procedure disposereference(var r : preference);
  632. begin
  633. dispose(r);
  634. r:=nil;
  635. end;
  636. function newreference(const r : treference) : preference;
  637. var
  638. p : preference;
  639. begin
  640. new(p);
  641. p^:=r;
  642. newreference:=p;
  643. end;
  644. function reg8toreg16(reg : tregister) : tregister;
  645. begin
  646. reg8toreg16:=reg32toreg16(reg8toreg32(reg));
  647. end;
  648. function reg16toreg8(reg : tregister) : tregister;
  649. begin
  650. reg16toreg8:=reg32toreg8(reg16toreg32(reg));
  651. end;
  652. function reg16toreg32(reg : tregister) : tregister;
  653. begin
  654. reg16toreg32:=tregister(byte(reg)-byte(R_EDI));
  655. end;
  656. function reg32toreg16(reg : tregister) : tregister;
  657. begin
  658. reg32toreg16:=tregister(byte(reg)+byte(R_EDI));
  659. end;
  660. function reg32toreg8(reg : tregister) : tregister;
  661. begin
  662. reg32toreg8:=tregister(byte(reg)+byte(R_DI));
  663. end;
  664. function reg8toreg32(reg : tregister) : tregister;
  665. begin
  666. reg8toreg32:=tregister(byte(reg)-byte(R_DI));
  667. end;
  668. function regtoreg8(reg : tregister) : tregister;
  669. begin
  670. regtoreg8:=reg32toreg8(reg);
  671. end;
  672. function regtoreg16(reg : tregister) : tregister;
  673. begin
  674. regtoreg16:=reg32toreg16(reg);
  675. end;
  676. function regtoreg32(reg : tregister) : tregister;
  677. begin
  678. regtoreg32:=reg;
  679. end;
  680. function regtoreg64(reg : tregister) : tregister;
  681. begin
  682. { to avoid warning }
  683. regtoreg64:=R_NO;
  684. end;
  685. function regsize(reg : tregister) : topsize;
  686. begin
  687. if reg in regset8bit then
  688. regsize:=S_B
  689. else if reg in regset16bit then
  690. regsize:=S_W
  691. else if reg in regset32bit then
  692. regsize:=S_L;
  693. end;
  694. procedure reset_reference(var ref : treference);
  695. begin
  696. FillChar(ref,sizeof(treference),0);
  697. end;
  698. function new_reference(base : tregister;offset : longint) : preference;
  699. var
  700. r : preference;
  701. begin
  702. new(r);
  703. FillChar(r^,sizeof(treference),0);
  704. r^.base:=base;
  705. r^.offset:=offset;
  706. new_reference:=r;
  707. end;
  708. {*****************************************************************************
  709. Instruction table
  710. *****************************************************************************}
  711. procedure DoneCpu;
  712. begin
  713. {exitproc:=saveexit; }
  714. {$ifndef NOAG386BIN}
  715. if assigned(instabcache) then
  716. dispose(instabcache);
  717. {$endif NOAG386BIN}
  718. end;
  719. procedure BuildInsTabCache;
  720. {$ifndef NOAG386BIN}
  721. var
  722. i : longint;
  723. {$endif}
  724. begin
  725. {$ifndef NOAG386BIN}
  726. new(instabcache);
  727. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  728. i:=0;
  729. while (i<InsTabEntries) do
  730. begin
  731. if InsTabCache^[InsTab[i].OPcode]=-1 then
  732. InsTabCache^[InsTab[i].OPcode]:=i;
  733. inc(i);
  734. end;
  735. {$endif NOAG386BIN}
  736. end;
  737. procedure InitCpu;
  738. begin
  739. {$ifndef NOAG386BIN}
  740. if not assigned(instabcache) then
  741. BuildInsTabCache;
  742. {$endif NOAG386BIN}
  743. end;
  744. end.
  745. {
  746. $Log$
  747. Revision 1.20 2000-01-07 01:14:23 peter
  748. * updated copyright to 2000
  749. Revision 1.19 1999/12/02 19:28:29 peter
  750. * more A_LOOP<Cond> to is_calljmp
  751. Revision 1.18 1999/12/02 11:26:41 peter
  752. * newoptimizations define added
  753. Revision 1.17 1999/11/09 23:06:45 peter
  754. * esi_offset -> selfpointer_offset to be newcg compatible
  755. * hcogegen -> cgbase fixes for newcg
  756. Revision 1.16 1999/11/06 14:34:20 peter
  757. * truncated log to 20 revs
  758. Revision 1.15 1999/10/27 16:11:28 peter
  759. * insns.dat is used to generate all i386*.inc files
  760. Revision 1.14 1999/10/14 14:57:51 florian
  761. - removed the hcodegen use in the new cg, use cgbase instead
  762. Revision 1.13 1999/09/15 20:35:39 florian
  763. * small fix to operator overloading when in MMX mode
  764. + the compiler uses now fldz and fld1 if possible
  765. + some fixes to floating point registers
  766. + some math. functions (arctan, ln, sin, cos, sqrt, sqr, pi) are now inlined
  767. * .... ???
  768. Revision 1.12 1999/09/10 18:48:01 florian
  769. * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
  770. * most things for stored properties fixed
  771. Revision 1.11 1999/09/08 16:04:05 peter
  772. * better support for object fields and more error checks for
  773. field accesses which create buggy code
  774. Revision 1.10 1999/08/28 15:34:19 florian
  775. * bug 519 fixed
  776. Revision 1.9 1999/08/19 20:05:09 michael
  777. + Fixed ifdef NOAG386BIN bug
  778. Revision 1.8 1999/08/19 13:02:10 pierre
  779. + label faillabel added for _FAIL support
  780. Revision 1.7 1999/08/18 13:26:23 jonas
  781. + some constants for the new optimizer
  782. Revision 1.6 1999/08/13 15:36:30 peter
  783. * fixed suffix writing for a_setcc
  784. Revision 1.5 1999/08/12 14:36:02 peter
  785. + KNI instructions
  786. Revision 1.4 1999/08/07 14:20:58 florian
  787. * some small problems fixed
  788. Revision 1.3 1999/08/05 14:58:09 florian
  789. * some fixes for the floating point registers
  790. * more things for the new code generator
  791. Revision 1.2 1999/08/04 13:45:25 florian
  792. + floating point register variables !!
  793. * pairegalloc is now generated for register variables
  794. Revision 1.1 1999/08/04 00:22:58 florian
  795. * renamed i386asm and i386base to cpuasm and cpubase
  796. Revision 1.10 1999/08/02 21:28:58 florian
  797. * the main branch psub.pas is now used for
  798. newcg compiler
  799. Revision 1.9 1999/08/02 21:01:45 michael
  800. * Moved toperand type back =(
  801. Revision 1.8 1999/08/02 20:45:49 michael
  802. * Moved toperand type to aasm
  803. Revision 1.7 1999/08/02 17:17:09 florian
  804. * small changes for the new code generator
  805. Revision 1.6 1999/06/06 15:53:15 peter
  806. * suffix adding can be turned of for some tasmops in att_nosuffix array
  807. }