cpubase.pas 30 KB

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