cpubase.pas 30 KB

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