cpubase.pas 27 KB

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