2
$Id: cpubase.pas,v 1.1 2005/02/13 18:56:44 florian Exp $
3
Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
5
Contains the base types for the ARM
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(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.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
****************************************************************************
23
{# Base unit for processor information. This unit contains
24
enumerations of registers, opcodes, sizes, and other
25
such things which are processor specific.
42
{*****************************************************************************
44
*****************************************************************************}
47
TAsmOp=(A_ABS_D,A_ABS_S,A_ADD,A_ADD_D,A_ADD_S,A_ADDI,A_ADDIU,A_ADDU,
48
A_AND,A_ANDI,A_BC1F,A_BC1FL,A_BC1T,A_BC1TL,A_BC2F,A_BC2FL,
49
A_BC2T,A_BC2TL,A_BEQ,A_BEQL,A_BGEZ,A_BGEZAL,A_BGEZALL,A_BGEZL,
50
A_BGTZ,A_BGTZL,A_BLEZ,A_BLEZL,A_BLTZ,A_BLTZAL,A_BLTZALL,A_BLTZL,
51
A_BNE,A_BNEL,A_BREAK,A_C_cond_D,A_C_cond_S,A_CACHE,A_CEIL_W_D,A_CEIL_W_S,
52
A_CFC1,A_CFC2,A_CLO,A_CLZ,A_COP2,A_CTC1,A_CTC2,A_CVT_D_S,
53
A_CVT_D_W,A_CVT_S_D,A_CVT_S_W,A_CVT_W_D,A_CVT_W_S,A_DIV,A_DIV_D,A_DIV_S,
54
A_DIVU,A_ERET,A_FLOOR_W_D,A_FLOOR_W_S,A_J,A_JAL,A_JALR,A_JR,
55
A_LB,A_LBU,A_LDC1,A_LDC2,A_LH,A_LHU,A_LL,A_LUI,
56
A_LW,A_LWC1,A_LWC2,A_LWL,A_LWR,A_MADD,A_MADDU,A_MFC0,
57
A_MFC1,A_MFC2,A_MFHI,A_MFLO,A_MOV_D,A_MOV_S,A_MOVF,A_MOVF_D,
58
A_MOVF_S,A_MOVN,A_MOVN_D,A_MOVN_S,A_MOVT,A_MOVT_D,A_MOVT_S,A_MOVZ,
59
A_MOVZ_D,A_MOVZ_S,A_MSUB,A_MSUBU,A_MTC0,A_MTC1,A_MTC2,A_MTHI,
60
A_MTLO,A_MUL,A_MUL_D,A_MUL_S,A_MULT,A_MULTU,A_NEG_D,A_NEG_S,
61
A_NOR,A_OR,A_ORI,A_PREF,A_ROUND_W_D,A_ROUND_W_S,A_SB,A_SC,
62
A_SDC1,A_SDC2,A_SH,A_SLL,A_SLLV,A_SLT,A_SLTI,A_SLTIU,
63
A_SLTU,A_SQRT_D,A_SQRT_S,A_SRA,A_SRAV,A_SRL,A_SRLV,A_SSNOP,
64
A_SUB,A_SUB_D,A_SUB_S,A_SUBU,A_SW,A_SWC1,A_SWC2,A_SWL,
65
A_SWR,A_SYNC,A_SYSCALL,A_TEQ,A_TEQI,A_TGE,A_TGEI,A_TGEIU,
66
A_TGEU,A_TLBP,A_TLBR,A_TLBWI,A_TLBWR,A_TLT,A_TLTI,A_TLTIU,
67
A_TLTU,A_TNE,A_TNEI,A_TRUNC_W_D,A_TRUNC_W_S,A_WAIT,A_XOR,A_XORI
70
{ This should define the array of instructions as string }
71
op2strtable=array[tasmop] of string[11];
74
{ First value of opcode enumeration }
75
firstop = low(tasmop);
76
{ Last value of opcode enumeration }
77
lastop = high(tasmop);
79
{*****************************************************************************
81
*****************************************************************************}
84
{ Number of registers used for indexing in tables }
85
tregisterindex=0..{$i rmipsnor.inc}-1;
88
{ Available Superregisters }
92
R_SUBWHOLE = R_SUBNONE;
94
{ Available Registers }
97
{ Integer Super registers first and last }
98
first_int_supreg = RS_R0;
99
first_int_imreg = $10;
101
{ Float Super register first and last }
102
first_fpu_supreg = RS_F0;
103
first_fpu_imreg = $08;
105
{ MM Super register first and last }
106
first_mm_supreg = RS_NO;
107
first_mm_imreg = RS_NO;
109
{$warning TODO Calculate bsstart}
110
regnumber_count_bsstart = 64;
112
regnumber_table : array[tregisterindex] of tregister = (
116
regstabs_table : array[tregisterindex] of shortint = (
120
regdwarf_table : array[tregisterindex] of shortint = (
123
{ registers which may be destroyed by calls }
124
VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
125
VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
128
totherregisterset = set of tregisterindex;
130
{*****************************************************************************
131
Instruction post fixes
132
*****************************************************************************}
134
{ ARM instructions load/store and arithmetic instructions
135
can have several instruction post fixes which are collected
138
TOpPostfix = (PF_None,
139
{ update condition flags
140
or floating point single }
142
{ floating point size }
143
PF_D,PF_E,PF_P,PF_EP,
145
PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
146
{ multiple load/store address modes }
147
PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA
150
TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
153
cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
155
PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,
156
PF_S,PF_D,PF_E,PF_None,PF_None);
158
oppostfix2str : array[TOpPostfix] of string[2] = ('',
161
'b','sb','bt','h','sh','t',
162
'ia','ib','da','db','fd','fa','ed','ea');
164
roundingmode2str : array[TRoundingMode] of string[1] = ('',
167
{*****************************************************************************
169
*****************************************************************************}
173
C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
174
C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
178
cond2str : array[TAsmCond] of string[2]=('',
179
'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
180
'ge','lt','gt','le','al','nv'
183
uppercond2str : array[TAsmCond] of string[2]=('',
184
'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
185
'GE','LT','GT','LE','AL','NV'
188
inverse_cond : array[TAsmCond] of TAsmCond=(C_None,
189
C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
190
C_LT,C_GE,C_LE,C_GT,C_None,C_None
193
{*****************************************************************************
195
*****************************************************************************}
198
TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
199
F_GE,F_LT,F_GT,F_LE);
201
{*****************************************************************************
203
*****************************************************************************}
205
taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
206
tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
208
tupdatereg = (UR_None,UR_Update);
210
pshifterop = ^tshifterop;
213
shiftmode : tshiftmode;
218
{*****************************************************************************
220
*****************************************************************************}
225
{ Constant defining possibly all registers which might require saving }
226
ALL_OTHERREGISTERS = [];
228
general_superregisters = [RS_R0..RS_PC];
230
{ Table of registers which can be allocated by the code generator
231
internally, when generating the code.
234
{ xxxregs = set of all possibly used registers of that type in the code }
236
{ usableregsxxx = set of all 32bit components of registers that can be }
237
{ possible allocated to a regvar or using getregisterxxx (this }
238
{ excludes registers which can be only used for parameter }
239
{ passing on ABI's that define this) }
240
{ c_countusableregsxxx = amount of registers in the usableregsxxx set }
243
{ to determine how many registers to use for regvars }
244
maxintscratchregs = 3;
245
usableregsint = [RS_R4..RS_R10];
246
c_countusableregsint = 7;
249
fpuregs = [RS_F0..RS_F7];
250
usableregsfpu = [RS_F4..RS_F7];
251
c_countusableregsfpu = 4;
253
mmregs = [RS_NO..RS_NO];
254
usableregsmm = [RS_NO..RS_NO];
255
c_countusableregsmm = 0;
260
c_countusableregsaddr = 0;
262
{*****************************************************************************
264
*****************************************************************************}
268
S_B,S_W,S_L,S_BW,S_BL,S_WL,
270
S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
273
{*****************************************************************************
275
*****************************************************************************}
279
varregs : Array [1..maxvarregs] of tsuperregister =
280
(RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
283
fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
284
(RS_F4,RS_F5,RS_F6,RS_F7);
286
{*****************************************************************************
287
Default generic sizes
288
*****************************************************************************}
290
{ Defines the default address size for a processor, }
292
{ the natural int size for a processor, }
294
{ the maximum float size for a processor, }
296
{ the size of a vector register for a processor }
299
{*****************************************************************************
300
Generic Register names
301
*****************************************************************************}
303
{ Stack pointer register }
304
NR_STACK_POINTER_REG = NR_R13;
305
RS_STACK_POINTER_REG = RS_R13;
306
{ Frame pointer register }
307
RS_FRAME_POINTER_REG = RS_R11;
308
NR_FRAME_POINTER_REG = NR_R11;
309
{ Register for addressing absolute data in a position independant way,
310
such as in PIC code. The exact meaning is ABI specific. For
311
further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
313
NR_PIC_OFFSET_REG = NR_R9;
314
{ Results are returned in this register (32-bit values) }
315
NR_FUNCTION_RETURN_REG = NR_R0;
316
RS_FUNCTION_RETURN_REG = RS_R0;
317
{ Low part of 64bit return value }
318
NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
319
RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
320
{ High part of 64bit return value }
321
NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
322
RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
323
{ The value returned from a function is available in this register }
324
NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
325
RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
326
{ The lowh part of 64bit value returned from a function }
327
NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
328
RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
329
{ The high part of 64bit value returned from a function }
330
NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
331
RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
333
NR_FPU_RESULT_REG = NR_F0;
335
NR_MM_RESULT_REG = NR_NO;
337
NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
339
{ Offset where the parent framepointer is pushed }
340
PARENT_FRAMEPOINTER_OFFSET = 0;
342
{*****************************************************************************
343
GCC /ABI linking information
344
*****************************************************************************}
347
{ Registers which must be saved when calling a routine declared as
348
cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
349
saved should be the ones as defined in the target ABI and / or GCC.
351
This value can be deduced from the CALLED_USED_REGISTERS array in the
354
saved_standard_registers : array[0..8] of tsuperregister =
355
(RS_R16,RS_R17,RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R30);
356
{ Required parameter alignment when calling a routine declared as
357
stdcall and cdecl. The alignment value should be the one defined
358
by GCC or the target ABI.
360
The value of this constant is equal to the constant
361
PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
366
{*****************************************************************************
368
*****************************************************************************}
370
{ Returns the tcgsize corresponding with the size of reg.}
371
function reg_cgsize(const reg: tregister) : tcgsize;
372
function cgsize2subreg(s:Tcgsize):Tsubregister;
373
function is_calljmp(o:tasmop):boolean;
374
procedure inverse_flags(var f: TResFlags);
375
function flags_to_cond(const f: TResFlags) : TAsmCond;
376
function findreg_by_number(r:Tregister):tregisterindex;
377
function std_regnum_search(const s:string):Tregister;
378
function std_regname(r:Tregister):string;
380
procedure shifterop_reset(var so : tshifterop);
381
function is_pc(const r : tregister) : boolean;
390
std_regname_table : array[tregisterindex] of string[7] = (
394
regnumber_index : array[tregisterindex] of tregisterindex = (
398
std_regname_index : array[tregisterindex] of tregisterindex = (
403
function cgsize2subreg(s:Tcgsize):Tsubregister;
405
cgsize2subreg:=R_SUBWHOLE;
409
function reg_cgsize(const reg: tregister): tcgsize;
410
const subreg2cgsize:array[Tsubregister] of Tcgsize =
411
(OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO);
413
case getregtype(reg) of
419
internalerror(200303181);
424
function is_calljmp(o:tasmop):boolean;
426
{ This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
427
To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
428
is_calljmp:= o in [A_J,A_JAL,A_JALR,{ A_JALX, }A_JR,
429
A_BEQ,A_BNE,A_BGEZ,A_BGEZAL,A_BGTZ,A_BLEZ,A_BLTZ,A_BLTZAL,
430
A_BEQL,A_BGEZALL,A_BGEZL,A_BGTZL,A_BLEZL,A_BLTZALL,A_BLTZL,A_BNEL];
434
procedure inverse_flags(var f: TResFlags);
436
inv_flags: array[TResFlags] of TResFlags =
437
(F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
438
F_LT,F_GE,F_LE,F_GT);
444
function flags_to_cond(const f: TResFlags) : TAsmCond;
446
flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
447
(C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
448
C_GE,C_LT,C_GT,C_LE);
450
if f>high(flag_2_cond) then
451
internalerror(200112301);
452
result:=flag_2_cond[f];
456
function findreg_by_number(r:Tregister):tregisterindex;
458
result:=rgBase.findreg_by_number_table(r,regnumber_index);
462
function std_regnum_search(const s:string):Tregister;
464
result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
468
function std_regname(r:Tregister):string;
472
p:=findreg_by_number_table(r,regnumber_index);
474
result:=std_regname_table[p]
476
result:=generic_regname(r);
480
procedure shifterop_reset(var so : tshifterop);
482
FillChar(so,sizeof(so),0);
486
function is_pc(const r : tregister) : boolean;
493
$Log: cpubase.pas,v $
494
Revision 1.1 2005/02/13 18:56:44 florian