cpubase.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  4. Contains the base types for the ARM
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {# Base unit for processor information. This unit contains
  19. enumerations of registers, opcodes, sizes, and other
  20. such things which are processor specific.
  21. }
  22. unit cpubase;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. cutils,cclasses,
  27. globals,
  28. cpuinfo,
  29. aasmbase,
  30. cginfo;
  31. {*****************************************************************************
  32. Assembler Opcodes
  33. *****************************************************************************}
  34. type
  35. TAsmOp=(A_ADC,A_ADD,A_AND,A_N,A_BIC,A_BKPT,A_BL,A_BLX,A_BX,
  36. A_CDP,A_CDP2,A_CLZ,A_CMN,A_CMP,A_EOR,A_LDC,_A_LDC2,
  37. A_LDM,A_LDR,A_LDRB,A_LDRD,A_LDRBT,A_LDRH,A_LDRSB,
  38. A_LDRSH,A_LDRT,A_MCR,A_MCR2,A_MCRR,A_MLA,A_MOV,
  39. A_MRC,A_MRC2,A_MRRC,A_RS,A_MSR,A_MUL,A_MVN,
  40. A_ORR,A_PLD,A_QADD,A_QDADD,A_QDSUB,A_QSUB,A_RSB,A_RSC,
  41. A_SBC,A_SMLAL.A_SMLA,A_SMLAL,A_SMLAW,A_SMULL,A_SMUL,
  42. A_SMULW,A_STC,A_STC2,A_STM,A_STR,A_STRB,A_STRBT,A_STRD,
  43. A_STRH,A_STRT,A_SUB,A_SWI,A_SWP,A_SWPB,A_TEQ,A_TST.
  44. A_UMLAL,A_UMULL
  45. { FPU coprocessor codes }
  46. { Vec unit coprocessor codes }
  47. );
  48. { This should define the array of instructions as string }
  49. op2strtable=array[tasmop] of string[11];
  50. Const
  51. { First value of opcode enumeration }
  52. firstop = low(tasmop);
  53. { Last value of opcode enumeration }
  54. lastop = high(tasmop);
  55. {*****************************************************************************
  56. Operand Sizes
  57. *****************************************************************************}
  58. type
  59. topsize = (S_NO,
  60. S_B,S_W,S_L,S_BW,S_BL,S_WL,
  61. S_IS,S_IL,S_IQ,
  62. S_FS,S_FL,S_FX,S_D,S_Q,S_FV,
  63. S_NEAR,S_FAR,S_SHORT
  64. );
  65. {*****************************************************************************
  66. Registers
  67. *****************************************************************************}
  68. type
  69. {# Enumeration for all possible registers for cpu. It
  70. is to note that all registers of the same type
  71. (for example all FPU registers), should be grouped
  72. together.
  73. }
  74. { don't change the order }
  75. { it's used by the register size conversions }
  76. toldregister = (R_NO,
  77. R_RAX,R_RCX,R_RDX,R_RBX,R_RSP,R_RBP,R_RSI,R_RDI,
  78. R_R0,R_R1,R_R2,R_R3,R_R4,R_R5,R_R6,R_R7,
  79. R_R8,R_R9,R_R10,R_R11,R_R12,R_R13,R_R14,R_PC,
  80. R_CPSR
  81. );
  82. type
  83. tnewregister=word;
  84. Tregister = packed record
  85. enum : Toldregister;
  86. { This is a word for now, change to cardinal
  87. when the old register coding is away.}
  88. number : Tnewregister;
  89. end;
  90. Tsuperregister = byte;
  91. Tsubregister = byte;
  92. { A type to store register locations for 64 Bit values. }
  93. tregister64 = packed record
  94. reglo,reghi : tregister;
  95. end;
  96. { alias for compact code }
  97. treg64 = tregister64;
  98. { Set type definition for registers }
  99. tregisterset = set of tregister;
  100. tsupregset = set of tsuperregister;
  101. { Type definition for the array of string of register names }
  102. reg2strtable = array[tregister] of string[6];
  103. const
  104. {# First register in the tregister enumeration }
  105. firstreg = low(tregister);
  106. {# Last register in the tregister enumeration }
  107. lastreg = high(tregister);
  108. firstsreg = R_CS;
  109. lastsreg = R_GS;
  110. regset8bit : tregisterset = [R_AL..R_DH];
  111. regset16bit : tregisterset = [R_AX..R_DI,R_CS..R_SS];
  112. regset32bit : tregisterset = [R_EAX..R_EDI];
  113. { Convert reg to opsize }
  114. reg2opsize : array[firstreg..lastreg] of topsize = (S_NO,
  115. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  116. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  117. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  118. S_W,S_W,S_W,S_W,S_W,S_W,
  119. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  120. S_L,S_L,S_L,S_L,S_L,S_L,
  121. S_L,S_L,S_L,S_L,
  122. S_L,S_L,S_L,S_L,S_L,
  123. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D,
  124. S_D,S_D,S_D,S_D,S_D,S_D,S_D,S_D
  125. );
  126. {# Standard opcode string table (for each tasmop enumeration). The
  127. opcode strings should conform to the names as defined by the
  128. processor manufacturer.
  129. }
  130. std_op2str:op2strtable={$i i386int.inc}
  131. {# Standard register table (for each tregister enumeration). The
  132. register strings should conform to the the names as defined
  133. by the processor manufacturer
  134. }
  135. std_reg2str : reg2strtable = ('',
  136. 'eax','ecx','edx','ebx','esp','ebp','esi','edi',
  137. 'ax','cx','dx','bx','sp','bp','si','di',
  138. 'al','cl','dl','bl','ah','ch','bh','dh',
  139. 'cs','ds','es','ss','fs','gs',
  140. 'st','st(0)','st(1)','st(2)','st(3)','st(4)','st(5)','st(6)','st(7)',
  141. 'dr0','dr1','dr2','dr3','dr6','dr7',
  142. 'cr0','cr2','cr3','cr4',
  143. 'tr3','tr4','tr5','tr6','tr7',
  144. 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
  145. 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7'
  146. );
  147. {*****************************************************************************
  148. Conditions
  149. *****************************************************************************}
  150. type
  151. TAsmCond=(C_None,
  152. C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
  153. C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
  154. );
  155. const
  156. cond2str:array[TAsmCond] of string[2]=('',
  157. 'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
  158. 'ge','lt','gt','le','al','nv'
  159. );
  160. inverse_cond:array[TAsmCond] of TAsmCond=(C_None,
  161. );
  162. {*****************************************************************************
  163. Flags
  164. *****************************************************************************}
  165. type
  166. 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);
  167. {*****************************************************************************
  168. Reference
  169. *****************************************************************************}
  170. type
  171. trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
  172. { reference record }
  173. preference = ^treference;
  174. treference = packed record
  175. segment,
  176. base,
  177. index : tregister;
  178. scalefactor : byte;
  179. offset : longint;
  180. symbol : tasmsymbol;
  181. offsetfixup : longint;
  182. options : trefoptions;
  183. end;
  184. { reference record }
  185. pparareference = ^tparareference;
  186. tparareference = packed record
  187. index : tregister;
  188. offset : longint;
  189. end;
  190. {*****************************************************************************
  191. Operands
  192. *****************************************************************************}
  193. { Types of operand }
  194. toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
  195. toper=record
  196. ot : longint;
  197. case typ : toptype of
  198. top_none : ();
  199. top_reg : (reg:tregister);
  200. top_ref : (ref:preference);
  201. top_const : (val:aword);
  202. top_symbol : (sym:tasmsymbol;symofs:longint);
  203. end;
  204. {*****************************************************************************
  205. Generic Location
  206. *****************************************************************************}
  207. type
  208. TLoc=(
  209. LOC_INVALID, { added for tracking problems}
  210. LOC_CONSTANT, { constant value }
  211. LOC_JUMP, { boolean results only, jump to false or true label }
  212. LOC_FLAGS, { boolean results only, flags are set }
  213. LOC_CREFERENCE, { in memory constant value reference (cannot change) }
  214. LOC_REFERENCE, { in memory value }
  215. LOC_REGISTER, { in a processor register }
  216. LOC_CREGISTER, { Constant register which shouldn't be modified }
  217. LOC_FPUREGISTER, { FPU stack }
  218. LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
  219. LOC_MMXREGISTER, { MMX register }
  220. LOC_CMMXREGISTER, { MMX register variable }
  221. LOC_SSEREGISTER,
  222. LOC_CSSEREGISTER
  223. );
  224. { tparamlocation describes where a parameter for a procedure is stored.
  225. References are given from the caller's point of view. The usual
  226. TLocation isn't used, because contains a lot of unnessary fields.
  227. }
  228. tparalocation = packed record
  229. size : TCGSize;
  230. loc : TLoc;
  231. sp_fixup : longint;
  232. case TLoc of
  233. LOC_REFERENCE : (reference : tparareference);
  234. { segment in reference at the same place as in loc_register }
  235. LOC_REGISTER,LOC_CREGISTER : (
  236. case longint of
  237. 1 : (register,registerhigh : tregister);
  238. { overlay a registerlow }
  239. 2 : (registerlow : tregister);
  240. { overlay a 64 Bit register type }
  241. 3 : (reg64 : tregister64);
  242. 4 : (register64 : tregister64);
  243. );
  244. { it's only for better handling }
  245. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  246. end;
  247. tlocation = packed record
  248. loc : TLoc;
  249. size : TCGSize;
  250. case TLoc of
  251. LOC_FLAGS : (resflags : tresflags);
  252. LOC_CONSTANT : (
  253. case longint of
  254. 1 : (value : AWord);
  255. { can't do this, this layout depends on the host cpu. Use }
  256. { lo(valueqword)/hi(valueqword) instead (JM) }
  257. { 2 : (valuelow, valuehigh:AWord); }
  258. { overlay a complete 64 Bit value }
  259. 3 : (valueqword : qword);
  260. );
  261. LOC_CREFERENCE,
  262. LOC_REFERENCE : (reference : treference);
  263. { segment in reference at the same place as in loc_register }
  264. LOC_REGISTER,LOC_CREGISTER : (
  265. case longint of
  266. 1 : (register,registerhigh,segment : tregister);
  267. { overlay a registerlow }
  268. 2 : (registerlow : tregister);
  269. { overlay a 64 Bit register type }
  270. 3 : (reg64 : tregister64);
  271. 4 : (register64 : tregister64);
  272. );
  273. { it's only for better handling }
  274. LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
  275. end;
  276. {*****************************************************************************
  277. Constants
  278. *****************************************************************************}
  279. const
  280. { declare aliases }
  281. LOC_MMREGISTER = LOC_SSEREGISTER;
  282. LOC_CMMREGISTER = LOC_CSSEREGISTER;
  283. max_operands = 3;
  284. lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER,
  285. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER];
  286. {# Constant defining possibly all registers which might require saving }
  287. ALL_REGISTERS = [firstreg..lastreg];
  288. general_registers = [R_EAX,R_EBX,R_ECX,R_EDX];
  289. {# low and high of the available maximum width integer general purpose }
  290. { registers }
  291. LoGPReg = R_EAX;
  292. HiGPReg = R_EDX;
  293. {# low and high of every possible width general purpose register (same as }
  294. { above on most architctures apart from the 80x86) }
  295. LoReg = R_EAX;
  296. HiReg = R_DH;
  297. {# Table of registers which can be allocated by the code generator
  298. internally, when generating the code.
  299. }
  300. { legend: }
  301. { xxxregs = set of all possibly used registers of that type in the code }
  302. { generator }
  303. { usableregsxxx = set of all 32bit components of registers that can be }
  304. { possible allocated to a regvar or using getregisterxxx (this }
  305. { excludes registers which can be only used for parameter }
  306. { passing on ABI's that define this) }
  307. { c_countusableregsxxx = amount of registers in the usableregsxxx set }
  308. maxintregs = 4;
  309. intregs = [R_EAX..R_BL];
  310. usableregsint = [R_EAX,R_EBX,R_ECX,R_EDX];
  311. c_countusableregsint = 4;
  312. maxfpuregs = 8;
  313. fpuregs = [R_ST0..R_ST7];
  314. usableregsfpu = [];
  315. c_countusableregsfpu = 0;
  316. mmregs = [R_MM0..R_MM7];
  317. usableregsmm = [R_MM0..R_MM7];
  318. c_countusableregsmm = 8;
  319. firstsaveintreg = R_EAX;
  320. lastsaveintreg = R_EBX;
  321. firstsavefpureg = R_NO;
  322. lastsavefpureg = R_NO;
  323. firstsavemmreg = R_MM0;
  324. lastsavemmreg = R_MM7;
  325. maxvarregs = 4;
  326. varregs : array[1..maxvarregs] of tregister =
  327. (R_EBX,R_EDX,R_ECX,R_EAX);
  328. maxfpuvarregs = 8;
  329. {# Registers which are defined as scratch and no need to save across
  330. routine calls or in assembler blocks.
  331. }
  332. max_scratch_regs = 1;
  333. scratch_regs : array[1..max_scratch_regs] of tregister = (R_EDI);
  334. {*****************************************************************************
  335. GDB Information
  336. *****************************************************************************}
  337. {# Register indexes for stabs information, when some
  338. parameters or variables are stored in registers.
  339. Taken from i386.c (dbx_register_map) and i386.h
  340. (FIXED_REGISTERS) from GCC 3.x source code
  341. }
  342. stab_regindex : array[tregister] of shortint =
  343. (-1,
  344. 0,1,2,3,4,5,6,7,
  345. 0,1,2,3,4,5,6,7,
  346. 0,1,2,3,0,1,2,3,
  347. -1,-1,-1,-1,-1,-1,
  348. 12,12,13,14,15,16,17,18,19,
  349. -1,-1,-1,-1,-1,-1,
  350. -1,-1,-1,-1,
  351. -1,-1,-1,-1,-1,
  352. 29,30,31,32,33,34,35,36,
  353. 21,22,23,24,25,26,27,28
  354. );
  355. {*****************************************************************************
  356. Default generic sizes
  357. *****************************************************************************}
  358. {# Defines the default address size for a processor, }
  359. OS_ADDR = OS_32;
  360. {# the natural int size for a processor, }
  361. OS_INT = OS_32;
  362. {# the maximum float size for a processor, }
  363. OS_FLOAT = OS_F80;
  364. {# the size of a vector register for a processor }
  365. OS_VECTOR = OS_M64;
  366. {*****************************************************************************
  367. Generic Register names
  368. *****************************************************************************}
  369. {# Stack pointer register }
  370. stack_pointer_reg = R_ESP;
  371. {# Frame pointer register }
  372. frame_pointer_reg = R_EBP;
  373. {# Self pointer register : contains the instance address of an
  374. object or class. }
  375. self_pointer_reg = R_ESI;
  376. {# Register for addressing absolute data in a position independant way,
  377. such as in PIC code. The exact meaning is ABI specific. For
  378. further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
  379. }
  380. pic_offset_reg = R_EBX;
  381. {# Results are returned in this register (32-bit values) }
  382. accumulator = R_EAX;
  383. {# Hi-Results are returned in this register (64-bit value high register) }
  384. accumulatorhigh = R_EDX;
  385. { WARNING: don't change to R_ST0!! See comments above implementation of }
  386. { a_loadfpu* methods in rgcpu (JM) }
  387. fpu_result_reg = R_ST;
  388. mmresultreg = R_MM0;
  389. {*****************************************************************************
  390. GCC /ABI linking information
  391. *****************************************************************************}
  392. const
  393. {# Registers which must be saved when calling a routine declared as
  394. cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
  395. saved should be the ones as defined in the target ABI and / or GCC.
  396. This value can be deduced from the CALLED_USED_REGISTERS array in the
  397. GCC source.
  398. }
  399. std_saved_registers = [R_ESI,R_EDI,R_EBX];
  400. {# Required parameter alignment when calling a routine declared as
  401. stdcall and cdecl. The alignment value should be the one defined
  402. by GCC or the target ABI.
  403. The value of this constant is equal to the constant
  404. PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
  405. }
  406. std_param_align = 4;
  407. {*****************************************************************************
  408. CPU Dependent Constants
  409. *****************************************************************************}
  410. {*****************************************************************************
  411. Helpers
  412. *****************************************************************************}
  413. function is_calljmp(o:tasmop):boolean;
  414. function flags_to_cond(const f: TResFlags) : TAsmCond;
  415. implementation
  416. {*****************************************************************************
  417. Helpers
  418. *****************************************************************************}
  419. function is_calljmp(o:tasmop):boolean;
  420. begin
  421. case o of
  422. A_CALL,
  423. A_JCXZ,
  424. A_JECXZ,
  425. A_JMP,
  426. A_LOOP,
  427. A_LOOPE,
  428. A_LOOPNE,
  429. A_LOOPNZ,
  430. A_LOOPZ,
  431. A_Jcc :
  432. is_calljmp:=true;
  433. else
  434. is_calljmp:=false;
  435. end;
  436. end;
  437. function flags_to_cond(const f: TResFlags) : TAsmCond;
  438. const
  439. flags_2_cond : array[TResFlags] of TAsmCond =
  440. (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE);
  441. begin
  442. result := flags_2_cond[f];
  443. end;
  444. end.
  445. {
  446. $Log$
  447. Revision 1.2 2003-07-26 00:55:57 florian
  448. * basic stuff fixed
  449. Revision 1.1 2003/07/21 16:35:30 florian
  450. * very basic stuff for the arm
  451. }