~ubuntu-branches/ubuntu/dapper/fpc/dapper

« back to all changes in this revision

Viewing changes to compiler/mips/cpubase.pas

  • Committer: Bazaar Package Importer
  • Author(s): Carlos Laviola
  • Date: 2005-05-30 11:59:10 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050530115910-x5pbzm4qqta4i94h
Tags: 2.0.0-2
debian/fp-compiler.postinst.in: forgot to reapply the patch that
correctly creates the slave link to pc(1).  (Closes: #310907)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{
 
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
 
4
 
 
5
    Contains the base types for the ARM
 
6
 
 
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.
 
11
 
 
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
 
 
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.
 
20
 
 
21
 ****************************************************************************
 
22
}
 
23
{# Base unit for processor information. This unit contains
 
24
   enumerations of registers, opcodes, sizes, and other
 
25
   such things which are processor specific.
 
26
}
 
27
unit cpubase;
 
28
 
 
29
{$i fpcdefs.inc}
 
30
 
 
31
  interface
 
32
 
 
33
    uses
 
34
      cutils,cclasses,
 
35
      globtype,globals,
 
36
      cpuinfo,
 
37
      aasmbase,
 
38
      cgbase
 
39
      ;
 
40
 
 
41
 
 
42
{*****************************************************************************
 
43
                                Assembler Opcodes
 
44
*****************************************************************************}
 
45
 
 
46
    type
 
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
 
68
             );
 
69
 
 
70
      { This should define the array of instructions as string }
 
71
      op2strtable=array[tasmop] of string[11];
 
72
 
 
73
    const
 
74
      { First value of opcode enumeration }
 
75
      firstop = low(tasmop);
 
76
      { Last value of opcode enumeration  }
 
77
      lastop  = high(tasmop);
 
78
 
 
79
{*****************************************************************************
 
80
                                  Registers
 
81
*****************************************************************************}
 
82
 
 
83
    type
 
84
      { Number of registers used for indexing in tables }
 
85
      tregisterindex=0..{$i rmipsnor.inc}-1;
 
86
 
 
87
    const
 
88
      { Available Superregisters }
 
89
      {$i rmipssup.inc}
 
90
 
 
91
      { No Subregisters }
 
92
      R_SUBWHOLE = R_SUBNONE;
 
93
 
 
94
      { Available Registers }
 
95
      {$i rmipscon.inc}
 
96
 
 
97
      { Integer Super registers first and last }
 
98
      first_int_supreg = RS_R0;
 
99
      first_int_imreg = $10;
 
100
 
 
101
      { Float Super register first and last }
 
102
      first_fpu_supreg    = RS_F0;
 
103
      first_fpu_imreg     = $08;
 
104
 
 
105
      { MM Super register first and last }
 
106
      first_mm_supreg    = RS_NO;
 
107
      first_mm_imreg     = RS_NO;
 
108
 
 
109
{$warning TODO Calculate bsstart}
 
110
      regnumber_count_bsstart = 64;
 
111
 
 
112
      regnumber_table : array[tregisterindex] of tregister = (
 
113
        {$i rmipsnum.inc}
 
114
      );
 
115
 
 
116
      regstabs_table : array[tregisterindex] of shortint = (
 
117
        {$i rmipssta.inc}
 
118
      );
 
119
 
 
120
      regdwarf_table : array[tregisterindex] of shortint = (
 
121
        {$i rmipsdwf.inc}
 
122
      );
 
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];
 
126
 
 
127
    type
 
128
      totherregisterset = set of tregisterindex;
 
129
 
 
130
{*****************************************************************************
 
131
                          Instruction post fixes
 
132
*****************************************************************************}
 
133
    type
 
134
      { ARM instructions load/store and arithmetic instructions
 
135
        can have several instruction post fixes which are collected
 
136
        in this enumeration
 
137
      }
 
138
      TOpPostfix = (PF_None,
 
139
        { update condition flags
 
140
          or floating point single }
 
141
        PF_S,
 
142
        { floating point size }
 
143
        PF_D,PF_E,PF_P,PF_EP,
 
144
        { load/store }
 
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
 
148
      );
 
149
 
 
150
      TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
 
151
 
 
152
    const
 
153
      cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
 
154
        PF_E,
 
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);
 
157
 
 
158
      oppostfix2str : array[TOpPostfix] of string[2] = ('',
 
159
        's',
 
160
        'd','e','p','ep',
 
161
        'b','sb','bt','h','sh','t',
 
162
        'ia','ib','da','db','fd','fa','ed','ea');
 
163
 
 
164
      roundingmode2str : array[TRoundingMode] of string[1] = ('',
 
165
        'p','m','z');
 
166
 
 
167
{*****************************************************************************
 
168
                                Conditions
 
169
*****************************************************************************}
 
170
 
 
171
    type
 
172
      TAsmCond=(C_None,
 
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
 
175
      );
 
176
 
 
177
    const
 
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'
 
181
      );
 
182
 
 
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'
 
186
      );
 
187
 
 
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
 
191
      );
 
192
 
 
193
{*****************************************************************************
 
194
                                   Flags
 
195
*****************************************************************************}
 
196
 
 
197
    type
 
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);
 
200
 
 
201
{*****************************************************************************
 
202
                                Operands
 
203
*****************************************************************************}
 
204
 
 
205
      taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
 
206
      tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
 
207
 
 
208
      tupdatereg = (UR_None,UR_Update);
 
209
 
 
210
      pshifterop = ^tshifterop;
 
211
 
 
212
      tshifterop = record
 
213
        shiftmode : tshiftmode;
 
214
        rs : tregister;
 
215
        shiftimm : byte;
 
216
      end;
 
217
 
 
218
{*****************************************************************************
 
219
                                 Constants
 
220
*****************************************************************************}
 
221
 
 
222
    const
 
223
      max_operands = 4;
 
224
 
 
225
      { Constant defining possibly all registers which might require saving }
 
226
      ALL_OTHERREGISTERS = [];
 
227
 
 
228
      general_superregisters = [RS_R0..RS_PC];
 
229
 
 
230
      { Table of registers which can be allocated by the code generator
 
231
        internally, when generating the code.
 
232
      }
 
233
      { legend:                                                                }
 
234
      { xxxregs = set of all possibly used registers of that type in the code  }
 
235
      {           generator                                                    }
 
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    }
 
241
 
 
242
      maxintregs = 15;
 
243
      { to determine how many registers to use for regvars }
 
244
      maxintscratchregs = 3;
 
245
      usableregsint = [RS_R4..RS_R10];
 
246
      c_countusableregsint = 7;
 
247
 
 
248
      maxfpuregs = 8;
 
249
      fpuregs = [RS_F0..RS_F7];
 
250
      usableregsfpu = [RS_F4..RS_F7];
 
251
      c_countusableregsfpu = 4;
 
252
 
 
253
      mmregs = [RS_NO..RS_NO];
 
254
      usableregsmm = [RS_NO..RS_NO];
 
255
      c_countusableregsmm  = 0;
 
256
 
 
257
      maxaddrregs = 0;
 
258
      addrregs    = [];
 
259
      usableregsaddr = [];
 
260
      c_countusableregsaddr = 0;
 
261
 
 
262
{*****************************************************************************
 
263
                                Operand Sizes
 
264
*****************************************************************************}
 
265
 
 
266
    type
 
267
      topsize = (S_NO,
 
268
        S_B,S_W,S_L,S_BW,S_BL,S_WL,
 
269
        S_IS,S_IL,S_IQ,
 
270
        S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
 
271
      );
 
272
 
 
273
{*****************************************************************************
 
274
                                 Constants
 
275
*****************************************************************************}
 
276
 
 
277
    const
 
278
      maxvarregs = 7;
 
279
      varregs : Array [1..maxvarregs] of tsuperregister =
 
280
                (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
 
281
 
 
282
      maxfpuvarregs = 4;
 
283
      fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
 
284
                (RS_F4,RS_F5,RS_F6,RS_F7);
 
285
 
 
286
{*****************************************************************************
 
287
                          Default generic sizes
 
288
*****************************************************************************}
 
289
 
 
290
      { Defines the default address size for a processor, }
 
291
      OS_ADDR = OS_32;
 
292
      { the natural int size for a processor,             }
 
293
      OS_INT = OS_32;
 
294
      { the maximum float size for a processor,           }
 
295
      OS_FLOAT = OS_F64;
 
296
      { the size of a vector register for a processor     }
 
297
      OS_VECTOR = OS_M32;
 
298
 
 
299
{*****************************************************************************
 
300
                          Generic Register names
 
301
*****************************************************************************}
 
302
 
 
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
 
312
      }
 
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;
 
332
 
 
333
      NR_FPU_RESULT_REG = NR_F0;
 
334
 
 
335
      NR_MM_RESULT_REG  = NR_NO;
 
336
 
 
337
      NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
 
338
 
 
339
      { Offset where the parent framepointer is pushed }
 
340
      PARENT_FRAMEPOINTER_OFFSET = 0;
 
341
 
 
342
{*****************************************************************************
 
343
                       GCC /ABI linking information
 
344
*****************************************************************************}
 
345
 
 
346
    const
 
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.
 
350
 
 
351
        This value can be deduced from the CALLED_USED_REGISTERS array in the
 
352
        GCC source.
 
353
      }
 
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.
 
359
 
 
360
        The value of this constant is equal to the constant
 
361
        PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
 
362
      }
 
363
      std_param_align = 4;
 
364
 
 
365
 
 
366
{*****************************************************************************
 
367
                                  Helpers
 
368
*****************************************************************************}
 
369
 
 
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;
 
379
 
 
380
    procedure shifterop_reset(var so : tshifterop);
 
381
    function is_pc(const r : tregister) : boolean;
 
382
 
 
383
  implementation
 
384
 
 
385
    uses
 
386
      rgBase,verbose;
 
387
 
 
388
 
 
389
    const
 
390
      std_regname_table : array[tregisterindex] of string[7] = (
 
391
        {$i rmipsstd.inc}
 
392
      );
 
393
 
 
394
      regnumber_index : array[tregisterindex] of tregisterindex = (
 
395
        {$i rmipsrni.inc}
 
396
      );
 
397
 
 
398
      std_regname_index : array[tregisterindex] of tregisterindex = (
 
399
        {$i rmipssri.inc}
 
400
      );
 
401
 
 
402
 
 
403
    function cgsize2subreg(s:Tcgsize):Tsubregister;
 
404
      begin
 
405
        cgsize2subreg:=R_SUBWHOLE;
 
406
      end;
 
407
 
 
408
 
 
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);
 
412
      begin
 
413
        case getregtype(reg) of
 
414
          R_INTREGISTER :
 
415
            reg_cgsize:=OS_32;
 
416
          R_FPUREGISTER :
 
417
            reg_cgsize:=OS_F80;
 
418
          else
 
419
            internalerror(200303181);
 
420
          end;
 
421
        end;
 
422
 
 
423
 
 
424
    function is_calljmp(o:tasmop):boolean;
 
425
      begin
 
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];
 
431
      end;
 
432
 
 
433
 
 
434
    procedure inverse_flags(var f: TResFlags);
 
435
      const
 
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);
 
439
      begin
 
440
        f:=inv_flags[f];
 
441
      end;
 
442
 
 
443
 
 
444
    function flags_to_cond(const f: TResFlags) : TAsmCond;
 
445
      const
 
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);
 
449
      begin
 
450
        if f>high(flag_2_cond) then
 
451
          internalerror(200112301);
 
452
        result:=flag_2_cond[f];
 
453
      end;
 
454
 
 
455
 
 
456
    function findreg_by_number(r:Tregister):tregisterindex;
 
457
      begin
 
458
        result:=rgBase.findreg_by_number_table(r,regnumber_index);
 
459
      end;
 
460
 
 
461
 
 
462
    function std_regnum_search(const s:string):Tregister;
 
463
      begin
 
464
        result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
 
465
      end;
 
466
 
 
467
 
 
468
    function std_regname(r:Tregister):string;
 
469
      var
 
470
        p : tregisterindex;
 
471
      begin
 
472
        p:=findreg_by_number_table(r,regnumber_index);
 
473
        if p<>0 then
 
474
          result:=std_regname_table[p]
 
475
        else
 
476
          result:=generic_regname(r);
 
477
      end;
 
478
 
 
479
 
 
480
    procedure shifterop_reset(var so : tshifterop);
 
481
      begin
 
482
        FillChar(so,sizeof(so),0);
 
483
      end;
 
484
 
 
485
 
 
486
    function is_pc(const r : tregister) : boolean;
 
487
      begin
 
488
        is_pc:=(r=NR_R15);
 
489
      end;
 
490
 
 
491
end.
 
492
{
 
493
  $Log: cpubase.pas,v $
 
494
  Revision 1.1  2005/02/13 18:56:44  florian
 
495
    + basic mips stuff
 
496
}