瀏覽代碼

+ basic mips stuff

florian 20 年之前
父節點
當前提交
f58fcdf401

+ 376 - 0
compiler/mips/aasmcpu.pas

@@ -0,0 +1,376 @@
+{
+    $Id$
+    Copyright (c) 2003 by Florian Klaempfl
+
+    Contains the assembler object for the ARM
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  cclasses,aasmtai,
+  aasmbase,globtype,globals,verbose,
+  cpubase,cpuinfo,cgbase,cgutils;
+
+    const
+      { "mov reg,reg" source operand number }
+      O_MOV_SOURCE = 1;
+      { "mov reg,reg" source operand number }
+      O_MOV_DEST = 0;
+
+    type
+      taicpu = class(tai_cpu_abstract)
+         constructor op_none(op : tasmop);
+
+         constructor op_reg(op : tasmop;_op1 : tregister);
+         constructor op_const(op : tasmop;_op1 : longint);
+
+         constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+         constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+         constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+
+         constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
+
+         constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+         constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+         constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
+         constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+         { SFM/LFM }
+         constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+
+         { this is for Jmp instructions }
+         constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+         constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+         constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+         constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
+         constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+         function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+         function spilling_get_operation_type(opnr: longint): topertype;override;
+      end;
+      tai_align = class(tai_align_abstract)
+        { nothing to add }
+      end;
+
+    function spilling_create_load(const ref:treference;r:tregister): tai;
+    function spilling_create_store(r:tregister; const ref:treference): tai;
+
+    procedure InitAsm;
+    procedure DoneAsm;
+
+
+implementation
+
+  uses
+    cutils,rgobj,itcpugas;
+
+
+{*****************************************************************************
+                                 taicpu Constructors
+*****************************************************************************}
+
+    constructor taicpu.op_none(op : tasmop);
+      begin
+         inherited create(op);
+      end;
+
+
+    constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadreg(0,_op1);
+      end;
+
+
+    constructor taicpu.op_const(op : tasmop;_op1 : longint);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadconst(0,aint(_op1));
+      end;
+
+
+    constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+      end;
+
+
+    constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadconst(1,aint(_op2));
+      end;
+
+
+    constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadref(1,_op2);
+      end;
+
+
+    constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+      begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+      end;
+
+
+     constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadconst(2,aint(_op3));
+      end;
+
+
+    constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+      begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadconst(1,_op2);
+         loadref(2,_op3);
+      end;
+
+
+     constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadsymbol(0,_op3,_op3ofs);
+      end;
+
+
+     constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+       begin
+         inherited create(op);
+         ops:=3;
+         loadreg(0,_op1);
+         loadreg(1,_op2);
+         loadref(2,_op3);
+      end;
+
+
+    constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+      begin
+         inherited create(op);
+         condition:=cond;
+         ops:=1;
+         loadsymbol(0,_op1,0);
+      end;
+
+
+    constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadsymbol(0,_op1,0);
+      end;
+
+
+    constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+      begin
+         inherited create(op);
+         ops:=1;
+         loadsymbol(0,_op1,_op1ofs);
+      end;
+
+
+     constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadreg(0,_op1);
+         loadsymbol(1,_op2,_op2ofs);
+      end;
+
+
+    constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+      begin
+         inherited create(op);
+         ops:=2;
+         loadsymbol(0,_op1,_op1ofs);
+         loadref(1,_op2);
+      end;
+
+
+{ ****************************** newra stuff *************************** }
+
+    function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+      begin
+        { allow the register allocator to remove unnecessary moves }
+        result:=(((opcode=A_MOVE) and (regtype = R_INTREGISTER)) or
+                 ((opcode=A_MVF) and (regtype = R_FPUREGISTER))
+                ) and
+                (condition=C_None) and
+                (ops=2) and
+                (oper[0]^.typ=top_reg) and
+                (oper[1]^.typ=top_reg) and
+                (oper[0]^.reg=oper[1]^.reg);
+      end;
+
+
+    function spilling_create_load(const ref:treference;r:tregister): tai;
+      begin
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=taicpu.op_reg_ref(A_LDR,r,ref);
+          R_FPUREGISTER :
+            { use lfm because we don't know the current internal format
+              and avoid exceptions
+            }
+            result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
+          else
+            internalerror(200401041);
+        end;
+      end;
+
+
+    function spilling_create_store(r:tregister; const ref:treference): tai;
+      begin
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=taicpu.op_reg_ref(A_STR,r,ref);
+          R_FPUREGISTER :
+            { use sfm because we don't know the current internal format
+              and avoid exceptions
+            }
+            result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
+          else
+            internalerror(200401041);
+        end;
+      end;
+
+
+    function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+      begin
+        case opcode of
+          A_ADC,A_ADD,A_AND,
+          A_EOR,A_CLZ,
+          A_LDR,A_LDRB,A_LDRD,A_LDRBT,A_LDRH,A_LDRSB,
+          A_LDRSH,A_LDRT,
+          A_MOV,A_MVN,A_MLA,A_MUL,
+          A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
+          A_SWP,A_SWPB,
+          A_LDF,A_FLT,A_FIX,
+          A_ADF,A_DVF,A_FDV,A_FML,
+          A_RFS,A_RFC,A_RDF,
+          A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
+          A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
+          A_LFM:
+            if opnr=0 then
+              result:=operand_write
+            else
+              result:=operand_read;
+          A_BIC,A_BKPT,A_B,A_BL,A_BLX,A_BX,
+          A_CMN,A_CMP,A_TEQ,A_TST,
+          A_CMF,A_CMFE,A_WFS,A_CNF:
+            result:=operand_read;
+          A_SMLAL,A_UMLAL:
+            if opnr in [0,1] then
+              result:=operand_readwrite
+            else
+              result:=operand_read;
+           A_SMULL,A_UMULL:
+            if opnr in [0,1] then
+              result:=operand_write
+            else
+              result:=operand_read;
+          A_STR,A_STRB,A_STRBT,A_STRD,
+          A_STRH,A_STRT,A_STF,A_SFM:
+            { important is what happens with the involved registers }
+            if opnr=0 then
+              result := operand_read
+            else
+              { check for pre/post indexed }
+              result := operand_read;
+          else
+            internalerror(200403151);
+        end;
+      end;
+
+
+    procedure InitAsm;
+      begin
+      end;
+
+
+    procedure DoneAsm;
+      begin
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  2005-02-13 18:56:44  florian
+    + basic mips stuff
+
+  Revision 1.36  2004/11/01 17:41:28  florian
+    * fixed arm compilation with cgutils
+    * ...
+
+  Revision 1.35  2004/10/24 17:32:53  florian
+    * fixed several arm compiler bugs
+
+  Revision 1.34  2004/07/04 15:22:34  florian
+    * fixed float spilling to use sfm/lfm instead of stf/ldf
+
+  Revision 1.33  2004/06/20 08:55:31  florian
+    * logs truncated
+
+  Revision 1.32  2004/06/16 20:07:10  florian
+    * dwarf branch merged
+
+  Revision 1.31.2.2  2004/06/13 10:51:17  florian
+    * fixed several register allocator problems (sparc/arm)
+
+  Revision 1.31.2.1  2004/06/12 17:01:01  florian
+    * fixed compilation of arm compiler
+
+  Revision 1.31  2004/03/29 19:19:35  florian
+    + arm floating point register saving implemented
+    * hopefully stabs generation for MacOSX fixed
+    + some defines for arm added
+
+  Revision 1.30  2004/03/15 22:20:13  florian
+    * handling of spilling improved
+
+}

+ 496 - 0
compiler/mips/cpubase.pas

@@ -0,0 +1,496 @@
+{
+    $Id$
+    Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+    Contains the base types for the ARM
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+   enumerations of registers, opcodes, sizes, and other
+   such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      cutils,cclasses,
+      globtype,globals,
+      cpuinfo,
+      aasmbase,
+      cgbase
+      ;
+
+
+{*****************************************************************************
+                                Assembler Opcodes
+*****************************************************************************}
+
+    type
+      TAsmOp=(A_ABS_D,A_ABS_S,A_ADD,A_ADD_D,A_ADD_S,A_ADDI,A_ADDIU,A_ADDU,
+              A_AND,A_ANDI,A_BC1F,A_BC1FL,A_BC1T,A_BC1TL,A_BC2F,A_BC2FL,
+              A_BC2T,A_BC2TL,A_BEQ,A_BEQL,A_BGEZ,A_BGEZAL,A_BGEZALL,A_BGEZL,
+              A_BGTZ,A_BGTZL,A_BLEZ,A_BLEZL,A_BLTZ,A_BLTZAL,A_BLTZALL,A_BLTZL,
+              A_BNE,A_BNEL,A_BREAK,A_C_cond_D,A_C_cond_S,A_CACHE,A_CEIL_W_D,A_CEIL_W_S,
+              A_CFC1,A_CFC2,A_CLO,A_CLZ,A_COP2,A_CTC1,A_CTC2,A_CVT_D_S,
+              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,
+              A_DIVU,A_ERET,A_FLOOR_W_D,A_FLOOR_W_S,A_J,A_JAL,A_JALR,A_JR,
+              A_LB,A_LBU,A_LDC1,A_LDC2,A_LH,A_LHU,A_LL,A_LUI,
+              A_LW,A_LWC1,A_LWC2,A_LWL,A_LWR,A_MADD,A_MADDU,A_MFC0,
+              A_MFC1,A_MFC2,A_MFHI,A_MFLO,A_MOV_D,A_MOV_S,A_MOVF,A_MOVF_D,
+              A_MOVF_S,A_MOVN,A_MOVN_D,A_MOVN_S,A_MOVT,A_MOVT_D,A_MOVT_S,A_MOVZ,
+              A_MOVZ_D,A_MOVZ_S,A_MSUB,A_MSUBU,A_MTC0,A_MTC1,A_MTC2,A_MTHI,
+              A_MTLO,A_MUL,A_MUL_D,A_MUL_S,A_MULT,A_MULTU,A_NEG_D,A_NEG_S,
+              A_NOR,A_OR,A_ORI,A_PREF,A_ROUND_W_D,A_ROUND_W_S,A_SB,A_SC,
+              A_SDC1,A_SDC2,A_SH,A_SLL,A_SLLV,A_SLT,A_SLTI,A_SLTIU,
+              A_SLTU,A_SQRT_D,A_SQRT_S,A_SRA,A_SRAV,A_SRL,A_SRLV,A_SSNOP,
+              A_SUB,A_SUB_D,A_SUB_S,A_SUBU,A_SW,A_SWC1,A_SWC2,A_SWL,
+              A_SWR,A_SYNC,A_SYSCALL,A_TEQ,A_TEQI,A_TGE,A_TGEI,A_TGEIU,
+              A_TGEU,A_TLBP,A_TLBR,A_TLBWI,A_TLBWR,A_TLT,A_TLTI,A_TLTIU,
+              A_TLTU,A_TNE,A_TNEI,A_TRUNC_W_D,A_TRUNC_W_S,A_WAIT,A_XOR,A_XORI
+             );
+
+      { This should define the array of instructions as string }
+      op2strtable=array[tasmop] of string[11];
+
+    const
+      { First value of opcode enumeration }
+      firstop = low(tasmop);
+      { Last value of opcode enumeration  }
+      lastop  = high(tasmop);
+
+{*****************************************************************************
+                                  Registers
+*****************************************************************************}
+
+    type
+      { Number of registers used for indexing in tables }
+      tregisterindex=0..{$i rmipsnor.inc}-1;
+
+    const
+      { Available Superregisters }
+      {$i rmipssup.inc}
+
+      { No Subregisters }
+      R_SUBWHOLE = R_SUBNONE;
+
+      { Available Registers }
+      {$i rmipscon.inc}
+
+      { Integer Super registers first and last }
+      first_int_supreg = RS_R0;
+      first_int_imreg = $10;
+
+      { Float Super register first and last }
+      first_fpu_supreg    = RS_F0;
+      first_fpu_imreg     = $08;
+
+      { MM Super register first and last }
+      first_mm_supreg    = RS_NO;
+      first_mm_imreg     = RS_NO;
+
+{$warning TODO Calculate bsstart}
+      regnumber_count_bsstart = 64;
+
+      regnumber_table : array[tregisterindex] of tregister = (
+        {$i rmipsnum.inc}
+      );
+
+      regstabs_table : array[tregisterindex] of shortint = (
+        {$i rmipssta.inc}
+      );
+
+      regdwarf_table : array[tregisterindex] of shortint = (
+        {$i rmipsdwf.inc}
+      );
+      { registers which may be destroyed by calls }
+      VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
+      VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
+
+    type
+      totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+                          Instruction post fixes
+*****************************************************************************}
+    type
+      { ARM instructions load/store and arithmetic instructions
+        can have several instruction post fixes which are collected
+        in this enumeration
+      }
+      TOpPostfix = (PF_None,
+        { update condition flags
+          or floating point single }
+        PF_S,
+        { floating point size }
+        PF_D,PF_E,PF_P,PF_EP,
+        { load/store }
+        PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
+        { multiple load/store address modes }
+        PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA
+      );
+
+      TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
+
+    const
+      cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
+        PF_E,
+        PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,
+        PF_S,PF_D,PF_E,PF_None,PF_None);
+
+      oppostfix2str : array[TOpPostfix] of string[2] = ('',
+        's',
+        'd','e','p','ep',
+        'b','sb','bt','h','sh','t',
+        'ia','ib','da','db','fd','fa','ed','ea');
+
+      roundingmode2str : array[TRoundingMode] of string[1] = ('',
+        'p','m','z');
+
+{*****************************************************************************
+                                Conditions
+*****************************************************************************}
+
+    type
+      TAsmCond=(C_None,
+        C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+        C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
+      );
+
+    const
+      cond2str : array[TAsmCond] of string[2]=('',
+        'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
+        'ge','lt','gt','le','al','nv'
+      );
+
+      uppercond2str : array[TAsmCond] of string[2]=('',
+        'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
+        'GE','LT','GT','LE','AL','NV'
+      );
+
+      inverse_cond : array[TAsmCond] of TAsmCond=(C_None,
+        C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+        C_LT,C_GE,C_LE,C_GT,C_None,C_None
+      );
+
+{*****************************************************************************
+                                   Flags
+*****************************************************************************}
+
+    type
+      TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
+        F_GE,F_LT,F_GT,F_LE);
+
+{*****************************************************************************
+                                Operands
+*****************************************************************************}
+
+      taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
+      tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
+
+      tupdatereg = (UR_None,UR_Update);
+
+      pshifterop = ^tshifterop;
+
+      tshifterop = record
+        shiftmode : tshiftmode;
+        rs : tregister;
+        shiftimm : byte;
+      end;
+
+{*****************************************************************************
+                                 Constants
+*****************************************************************************}
+
+    const
+      max_operands = 4;
+
+      { Constant defining possibly all registers which might require saving }
+      ALL_OTHERREGISTERS = [];
+
+      general_superregisters = [RS_R0..RS_PC];
+
+      { Table of registers which can be allocated by the code generator
+        internally, when generating the code.
+      }
+      { legend:                                                                }
+      { xxxregs = set of all possibly used registers of that type in the code  }
+      {           generator                                                    }
+      { usableregsxxx = set of all 32bit components of registers that can be   }
+      {           possible allocated to a regvar or using getregisterxxx (this }
+      {           excludes registers which can be only used for parameter      }
+      {           passing on ABI's that define this)                           }
+      { c_countusableregsxxx = amount of registers in the usableregsxxx set    }
+
+      maxintregs = 15;
+      { to determine how many registers to use for regvars }
+      maxintscratchregs = 3;
+      usableregsint = [RS_R4..RS_R10];
+      c_countusableregsint = 7;
+
+      maxfpuregs = 8;
+      fpuregs = [RS_F0..RS_F7];
+      usableregsfpu = [RS_F4..RS_F7];
+      c_countusableregsfpu = 4;
+
+      mmregs = [RS_NO..RS_NO];
+      usableregsmm = [RS_NO..RS_NO];
+      c_countusableregsmm  = 0;
+
+      maxaddrregs = 0;
+      addrregs    = [];
+      usableregsaddr = [];
+      c_countusableregsaddr = 0;
+
+{*****************************************************************************
+                                Operand Sizes
+*****************************************************************************}
+
+    type
+      topsize = (S_NO,
+        S_B,S_W,S_L,S_BW,S_BL,S_WL,
+        S_IS,S_IL,S_IQ,
+        S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+      );
+
+{*****************************************************************************
+                                 Constants
+*****************************************************************************}
+
+    const
+      maxvarregs = 7;
+      varregs : Array [1..maxvarregs] of tsuperregister =
+                (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+      maxfpuvarregs = 4;
+      fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
+                (RS_F4,RS_F5,RS_F6,RS_F7);
+
+{*****************************************************************************
+                          Default generic sizes
+*****************************************************************************}
+
+      { Defines the default address size for a processor, }
+      OS_ADDR = OS_32;
+      { the natural int size for a processor,             }
+      OS_INT = OS_32;
+      { the maximum float size for a processor,           }
+      OS_FLOAT = OS_F64;
+      { the size of a vector register for a processor     }
+      OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+                          Generic Register names
+*****************************************************************************}
+
+      { Stack pointer register }
+      NR_STACK_POINTER_REG = NR_R13;
+      RS_STACK_POINTER_REG = RS_R13;
+      { Frame pointer register }
+      RS_FRAME_POINTER_REG = RS_R11;
+      NR_FRAME_POINTER_REG = NR_R11;
+      { Register for addressing absolute data in a position independant way,
+        such as in PIC code. The exact meaning is ABI specific. For
+        further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+      }
+      NR_PIC_OFFSET_REG = NR_R9;
+      { Results are returned in this register (32-bit values) }
+      NR_FUNCTION_RETURN_REG = NR_R0;
+      RS_FUNCTION_RETURN_REG = RS_R0;
+      { Low part of 64bit return value }
+      NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
+      RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
+      { High part of 64bit return value }
+      NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
+      RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
+      { The value returned from a function is available in this register }
+      NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+      RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+      { The lowh part of 64bit value returned from a function }
+      NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+      RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+      { The high part of 64bit value returned from a function }
+      NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+      RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+      NR_FPU_RESULT_REG = NR_F0;
+
+      NR_MM_RESULT_REG  = NR_NO;
+
+      NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
+
+      { Offset where the parent framepointer is pushed }
+      PARENT_FRAMEPOINTER_OFFSET = 0;
+
+{*****************************************************************************
+                       GCC /ABI linking information
+*****************************************************************************}
+
+    const
+      { Registers which must be saved when calling a routine declared as
+        cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+        saved should be the ones as defined in the target ABI and / or GCC.
+
+        This value can be deduced from the CALLED_USED_REGISTERS array in the
+        GCC source.
+      }
+      saved_standard_registers : array[0..8] of tsuperregister =
+        (RS_R16,RS_R17,RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R30);
+      { Required parameter alignment when calling a routine declared as
+        stdcall and cdecl. The alignment value should be the one defined
+        by GCC or the target ABI.
+
+        The value of this constant is equal to the constant
+        PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+      }
+      std_param_align = 4;
+
+
+{*****************************************************************************
+                                  Helpers
+*****************************************************************************}
+
+    { Returns the tcgsize corresponding with the size of reg.}
+    function reg_cgsize(const reg: tregister) : tcgsize;
+    function cgsize2subreg(s:Tcgsize):Tsubregister;
+    function is_calljmp(o:tasmop):boolean;
+    procedure inverse_flags(var f: TResFlags);
+    function flags_to_cond(const f: TResFlags) : TAsmCond;
+    function findreg_by_number(r:Tregister):tregisterindex;
+    function std_regnum_search(const s:string):Tregister;
+    function std_regname(r:Tregister):string;
+
+    procedure shifterop_reset(var so : tshifterop);
+    function is_pc(const r : tregister) : boolean;
+
+  implementation
+
+    uses
+      rgBase,verbose;
+
+
+    const
+      std_regname_table : array[tregisterindex] of string[7] = (
+        {$i rmipsstd.inc}
+      );
+
+      regnumber_index : array[tregisterindex] of tregisterindex = (
+        {$i rmipsrni.inc}
+      );
+
+      std_regname_index : array[tregisterindex] of tregisterindex = (
+        {$i rmipssri.inc}
+      );
+
+
+    function cgsize2subreg(s:Tcgsize):Tsubregister;
+      begin
+        cgsize2subreg:=R_SUBWHOLE;
+      end;
+
+
+    function reg_cgsize(const reg: tregister): tcgsize;
+      const subreg2cgsize:array[Tsubregister] of Tcgsize =
+            (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO);
+      begin
+        case getregtype(reg) of
+          R_INTREGISTER :
+            reg_cgsize:=OS_32;
+          R_FPUREGISTER :
+            reg_cgsize:=OS_F80;
+          else
+            internalerror(200303181);
+          end;
+        end;
+
+
+    function is_calljmp(o:tasmop):boolean;
+      begin
+        { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
+          To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
+        is_calljmp:= o in [A_J,A_JAL,A_JALR,{ A_JALX, }A_JR,
+          A_BEQ,A_BNE,A_BGEZ,A_BGEZAL,A_BGTZ,A_BLEZ,A_BLTZ,A_BLTZAL,
+          A_BEQL,A_BGEZALL,A_BGEZL,A_BGTZL,A_BLEZL,A_BLTZALL,A_BLTZL,A_BNEL];
+      end;
+
+
+    procedure inverse_flags(var f: TResFlags);
+      const
+        inv_flags: array[TResFlags] of TResFlags =
+          (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
+          F_LT,F_GE,F_LE,F_GT);
+      begin
+        f:=inv_flags[f];
+      end;
+
+
+    function flags_to_cond(const f: TResFlags) : TAsmCond;
+      const
+        flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
+          (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+           C_GE,C_LT,C_GT,C_LE);
+      begin
+        if f>high(flag_2_cond) then
+          internalerror(200112301);
+        result:=flag_2_cond[f];
+      end;
+
+
+    function findreg_by_number(r:Tregister):tregisterindex;
+      begin
+        result:=rgBase.findreg_by_number_table(r,regnumber_index);
+      end;
+
+
+    function std_regnum_search(const s:string):Tregister;
+      begin
+        result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+      end;
+
+
+    function std_regname(r:Tregister):string;
+      var
+        p : tregisterindex;
+      begin
+        p:=findreg_by_number_table(r,regnumber_index);
+        if p<>0 then
+          result:=std_regname_table[p]
+        else
+          result:=generic_regname(r);
+      end;
+
+
+    procedure shifterop_reset(var so : tshifterop);
+      begin
+        FillChar(so,sizeof(so),0);
+      end;
+
+
+    function is_pc(const r : tregister) : boolean;
+      begin
+        is_pc:=(r=NR_R15);
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  2005-02-13 18:56:44  florian
+    + basic mips stuff
+}

+ 80 - 0
compiler/mips/cpuinfo.pas

@@ -0,0 +1,80 @@
+{
+    $Id$
+    Copyright (c) 1998-2002 by the Free Pascal development team
+
+    Basic Processor information for the ARM
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+  uses
+    globtype;
+
+Type
+   bestreal = double;
+   ts32real = single;
+   ts64real = double;
+   ts80real = type double;
+   ts128real = type double;
+   ts64comp = comp;
+
+   pbestreal=^bestreal;
+
+   { possible supported processors for this target }
+   tprocessors =
+      (no_processor,
+       mips32
+      );
+
+   tfputype =
+     (no_fpuprocessor,
+      fpu_fpu
+     );
+
+Const
+   {# Size of native extended floating point type }
+   extended_size = 8;
+   {# Size of a multimedia register               }
+   mmreg_size = 0;
+   { target cpu string (used by compiler options) }
+   target_cpu_string = 'mips';
+
+   { calling conventions supported by the code generator }
+   supported_calling_conventions : tproccalloptions = [
+     pocall_internproc,
+     pocall_compilerproc,
+     pocall_inline,
+     pocall_stdcall,
+     { same as stdcall only different name mangling }
+     pocall_cdecl,
+     { same as stdcall only different name mangling }
+     pocall_cppdecl
+   ];
+
+   processorsstr : array[tprocessors] of string[5] = ('',
+     'MIPS32'
+   );
+
+   fputypestr : array[tfputype] of string[6] = ('',
+     'FPU'
+   );
+
+
+Implementation
+
+end.
+{
+  $Log$
+  Revision 1.1  2005-02-13 18:56:44  florian
+    + basic mips stuff
+}

+ 130 - 0
compiler/mips/itcpugas.pas

@@ -0,0 +1,130 @@
+{
+    $Id$
+    Copyright (c) 1998-2005 by Florian Klaempfl
+
+    This unit contains the MIPS GAS instruction tables
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+  uses
+    cpubase,cgbase;
+
+
+  const
+    { Standard opcode string table (for each tasmop enumeration). The
+      opcode strings should conform to the names as defined by the
+      processor manufacturer.
+    }
+    gas_op2str : op2strtable = (
+              'abs_d','abs_s','add','add_d','add_s','addi','addiu','addu',
+              'and','andi','bc1f','bc1fl','bc1t','bc1tl','bc2f','bc2fl',
+              'bc2t','bc2tl','beq','beql','bgez','bgezal','bgezall','bgezl',
+              'bgtz','bgtzl','blez','blezl','bltz','bltzal','bltzall','bltzl',
+              'bne','bnel','break','c_cond_d','c_cond_s','cache','ceil_w_d','ceil_w_s',
+              'cfc1','cfc2','clo','clz','cop2','ctc1','ctc2','cvt_d_s',
+              'cvt_d_w','cvt_s_d','cvt_s_w','cvt_w_d','cvt_w_s','div','div_d','div_s',
+              'divu','eret','floor_w_d','floor_w_s','j','jal','jalr','jr',
+              'lb','lbu','ldc1','ldc2','lh','lhu','ll','lui',
+              'lw','lwc1','lwc2','lwl','lwr','madd','maddu','mfc0',
+              'mfc1','mfc2','mfhi','mflo','mov_d','mov_s','movf','movf_d',
+              'movf_s','movn','movn_d','movn_s','movt','movt_d','movt_s','movz',
+              'movz_d','movz_s','msub','msubu','mtc0','mtc1','mtc2','mthi',
+              'mtlo','mul','mul_d','mul_s','mult','multu','neg_d','neg_s',
+              'nor','or','ori','pref','round_w_d','round_w_s','sb','sc',
+              'sdc1','sdc2','sh','sll','sllv','slt','slti','sltiu',
+              'sltu','sqrt_d','sqrt_s','sra','srav','srl','srlv','ssnop',
+              'sub','sub_d','sub_s','subu','sw','swc1','swc2','swl',
+              'swr','sync','syscall','teq','teqi','tge','tgei','tgeiu',
+              'tgeu','tlbp','tlbr','tlbwi','tlbwr','tlt','tlti','tltiu',
+              'tltu','tne','tnei','trunc_w_d','trunc_w_s','wait','xor','xori'
+             );
+
+
+    function gas_regnum_search(const s:string):Tregister;
+    function gas_regname(r:Tregister):string;
+
+
+implementation
+
+    uses
+      cutils,verbose;
+
+    const
+      gas_regname_table : array[tregisterindex] of string[7] = (
+        {$i rmipsgas.inc}
+      );
+
+      gas_regname_index : array[tregisterindex] of tregisterindex = (
+        {$i rmipssri.inc}
+      );
+
+    function findreg_by_gasname(const s:string):tregisterindex;
+      var
+        i,p : tregisterindex;
+      begin
+        {Binary search.}
+        p:=0;
+        i:=regnumber_count_bsstart;
+        repeat
+          if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+            p:=p+i;
+          i:=i shr 1;
+        until i=0;
+        if gas_regname_table[gas_regname_index[p]]=s then
+          findreg_by_gasname:=gas_regname_index[p]
+        else
+          findreg_by_gasname:=0;
+      end;
+
+
+    function gas_regnum_search(const s:string):Tregister;
+      begin
+        result:=regnumber_table[findreg_by_gasname(s)];
+      end;
+
+
+    function gas_regname(r:Tregister):string;
+      var
+        p : tregisterindex;
+      begin
+        p:=findreg_by_number(r);
+        if p<>0 then
+          result:=gas_regname_table[p]
+        else
+          result:=generic_regname(r);
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  2005-02-13 18:56:44  florian
+    + basic mips stuff
+
+  Revision 1.4  2004/06/20 08:55:31  florian
+    * logs truncated
+
+  Revision 1.3  2004/03/13 18:45:40  florian
+    * floating compares fixed
+    * unary minus for floats fixed
+
+}

+ 93 - 0
compiler/mips/mipsreg.dat

@@ -0,0 +1,93 @@
+;
+; $Id$
+;
+; MIPS registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,0
+R1,$01,$01,r1,r1,1,1
+R2,$01,$02,r2,r2,2,2
+R3,$01,$03,r3,r3,3,3
+R4,$01,$04,r4,r4,4,4
+R5,$01,$05,r5,r5,5,5
+R6,$01,$06,r6,r6,6,6
+R7,$01,$07,r7,r7,7,7
+R8,$01,$08,r8,r8,8,8
+R9,$01,$09,r9,r9,9,9
+R10,$01,$0a,r10,r10,10,10
+R11,$01,$0b,r11,r11,11,11
+R12,$01,$0c,r12,r12,12,12
+R13,$01,$0d,r13,r13,13,13
+R14,$01,$0e,r14,r14,14,14
+R15,$01,$0f,r15,r15,15,15
+R16,$01,$10,r16,r16,16,16
+R17,$01,$11,r17,r17,17,17
+R18,$01,$12,r18,r18,18,18
+R19,$01,$13,r19,r19,19,19
+R20,$01,$14,r20,r20,20,20
+R21,$01,$15,r21,r21,21,21
+R22,$01,$16,r22,r22,22,22
+R23,$01,$17,r23,r23,23,23
+R24,$01,$18,r24,r24,24,24
+R25,$01,$19,r25,r25,25,25
+R26,$01,$1a,r26,r26,26,26
+R27,$01,$1b,r27,r27,27,27
+R28,$01,$1c,r28,r28,28,28
+R29,$01,$1d,r29,r29,29,29
+R30,$01,$1e,r30,r30,30,30
+R31,$01,$1f,r31,r31,31,31
+
+F0,$02,$00,F0,f0,32,32
+F1,$02,$01,F1,f1,33,33
+F2,$02,$02,F2,f2,34,34
+F3,$02,$03,F3,f3,35,35
+F4,$02,$04,F4,f4,36,36
+F5,$02,$05,F5,f5,37,37
+F6,$02,$06,F6,f6,38,38
+F7,$02,$07,F7,f7,39,39
+F8,$02,$08,F8,f8,40,40
+F9,$02,$09,F9,f9,41,41
+F10,$02,$0a,F10,f10,42,42
+F11,$02,$0b,F11,f11,43,43
+F12,$02,$0c,F12,f12,44,44
+F13,$02,$0d,F13,f13,45,45
+F14,$02,$0e,F14,f14,46,46
+F15,$02,$0f,F15,f15,47,47
+F16,$02,$10,F16,f16,48,48
+F17,$02,$11,F17,f17,49,49
+F18,$02,$12,F18,f18,50,50
+F19,$02,$13,F19,f19,51,51
+F20,$02,$14,F20,f20,52,52
+F21,$02,$15,F21,f21,53,53
+F22,$02,$16,F22,f22,54,54
+F23,$02,$17,F23,f23,55,55
+F24,$02,$18,F24,f24,56,56
+F25,$02,$19,F25,f25,57,57
+F26,$02,$1a,F26,f26,58,58
+F27,$02,$1b,F27,f27,59,59
+F28,$02,$1c,F28,f28,60,60
+F29,$02,$1d,F29,f29,61,61
+F30,$02,$1e,F30,f30,62,62
+F31,$02,$1f,F31,f31,63,63
+
+PC,$05,$00,PC,pc,-1,-1
+HI,$05,$01,HI,hi,68,68
+LO,$05,$02,LO,lo,69,69
+CR,$05,$03,CR,cr,70,70
+FCR0,$05,$04,FCR0,fcr0,71,71
+FCR25,$05,$05,FCR25,fcr25,72,72
+FCR26,$05,$06,FCR26,fcr26,73,73
+FCR28,$05,$07,FCR28,fcr28,74,74
+FCSR,$05,$08,FCSR,fcsr,75,75
+
+;
+; $Log$
+; Revision 1.1  2005-02-13 18:56:44  florian
+;   + basic mips stuff
+;
+;
+;

+ 75 - 0
compiler/mips/rmipscon.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_PC = tregister($05000000);
+NR_HI = tregister($05000001);
+NR_LO = tregister($05000002);
+NR_CR = tregister($05000003);
+NR_FCR0 = tregister($05000004);
+NR_FCR25 = tregister($05000005);
+NR_FCR26 = tregister($05000006);
+NR_FCR28 = tregister($05000007);
+NR_FCSR = tregister($05000008);

+ 75 - 0
compiler/mips/rmipsdwf.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75

+ 75 - 0
compiler/mips/rmipsdwrf.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75

+ 75 - 0
compiler/mips/rmipsgas.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'pc',
+'hi',
+'lo',
+'cr',
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'

+ 75 - 0
compiler/mips/rmipsgri.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+68,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+69,
+70,
+71,
+72,
+73,
+66,
+67,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10

+ 75 - 0
compiler/mips/rmipsgss.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'pc',
+'hi',
+'lo',
+'cr',
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'

+ 75 - 0
compiler/mips/rmipsmot.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'PC',
+'HI',
+'LO',
+'CR',
+'FCR0',
+'FCR25',
+'FCR26',
+'FCR28',
+'FCSR'

+ 75 - 0
compiler/mips/rmipsmri.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0

+ 2 - 0
compiler/mips/rmipsnor.inc

@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from mipsreg.dat }
+74

+ 75 - 0
compiler/mips/rmipsnum.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008)

+ 75 - 0
compiler/mips/rmipsrni.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73

+ 75 - 0
compiler/mips/rmipssri.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+68,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+69,
+70,
+71,
+72,
+73,
+66,
+0,
+67,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10

+ 75 - 0
compiler/mips/rmipssta.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75

+ 75 - 0
compiler/mips/rmipsstab.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75

+ 75 - 0
compiler/mips/rmipsstd.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'PC',
+'HI',
+'LO',
+'CR',
+'FCR0',
+'FCR25',
+'FCR26',
+'FCR28',
+'FCSR'

+ 75 - 0
compiler/mips/rmipssup.inc

@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_PC = $00;
+RS_HI = $01;
+RS_LO = $02;
+RS_CR = $03;
+RS_FCR0 = $04;
+RS_FCR25 = $05;
+RS_FCR26 = $06;
+RS_FCR28 = $07;
+RS_FCSR = $08;

+ 355 - 0
compiler/utils/mkmpsreg.pp

@@ -0,0 +1,355 @@
+{
+    $Id$
+    Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+    Convert mipsreg.dat to several .inc files for usage with
+    the Free pascal compiler
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program mkmipsreg;
+
+const Version = '1.00';
+      max_regcount = 200;
+
+var s : string;
+    i : longint;
+    line : longint;
+    regcount:byte;
+    regcount_bsstart:byte;
+    names,
+    regtypes,
+    supregs,
+    numbers,
+    stdnames,
+    gasnames,
+    dwarfs,
+    stabs : array[0..max_regcount-1] of string[63];
+    regnumber_index,
+    std_regname_index,
+    gas_regname_index,
+    mot_regname_index : array[0..max_regcount-1] of byte;
+
+{$ifndef FPC}
+  procedure readln(var t:text;var s:string);
+  var
+    c : char;
+    i : longint;
+  begin
+    c:=#0;
+    i:=0;
+    while (not eof(t)) and (c<>#10) do
+     begin
+       read(t,c);
+       if c<>#10 then
+        begin
+          inc(i);
+          s[i]:=c;
+        end;
+     end;
+    if (i>0) and (s[i]=#13) then
+     dec(i);
+    s[0]:=chr(i);
+  end;
+{$endif}
+
+function tostr(l : longint) : string;
+
+begin
+  str(l,tostr);
+end;
+
+function readstr : string;
+
+  var
+     result : string;
+
+  begin
+     result:='';
+     while (s[i]<>',') and (i<=length(s)) do
+       begin
+          result:=result+s[i];
+          inc(i);
+       end;
+     readstr:=result;
+  end;
+
+
+procedure readcomma;
+  begin
+     if s[i]<>',' then
+       begin
+         writeln('Missing "," at line ',line);
+         writeln('Line: "',s,'"');
+         halt(1);
+       end;
+     inc(i);
+  end;
+
+
+procedure skipspace;
+
+  begin
+     while (s[i] in [' ',#9]) do
+       inc(i);
+  end;
+
+procedure openinc(var f:text;const fn:string);
+begin
+  writeln('creating ',fn);
+  assign(f,fn);
+  rewrite(f);
+  writeln(f,'{ don''t edit, this file is generated from mipsreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+  writeln(f);
+  close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+  {Build the registernumber2regindex index.
+   Step 1: Fill.}
+  for i:=0 to regcount-1 do
+    regnumber_index[i]:=i;
+  {Step 2: Sort. We use a Shell-Metzner sort.}
+  p:=regcount_bsstart;
+  repeat
+    for h:=0 to regcount-p-1 do
+      begin
+        i:=h;
+        repeat
+          j:=i+p;
+          if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+            break;
+          t:=regnumber_index[i];
+          regnumber_index[i]:=regnumber_index[j];
+          regnumber_index[j]:=t;
+          if i<p then
+            break;
+          dec(i,p);
+        until false;
+      end;
+    p:=p shr 1;
+  until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+  {Build the registernumber2regindex index.
+   Step 1: Fill.}
+  for i:=0 to regcount-1 do
+    std_regname_index[i]:=i;
+  {Step 2: Sort. We use a Shell-Metzner sort.}
+  p:=regcount_bsstart;
+  repeat
+    for h:=0 to regcount-p-1 do
+      begin
+        i:=h;
+        repeat
+          j:=i+p;
+          if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+            break;
+          t:=std_regname_index[i];
+          std_regname_index[i]:=std_regname_index[j];
+          std_regname_index[j]:=t;
+          if i<p then
+            break;
+          dec(i,p);
+        until false;
+      end;
+    p:=p shr 1;
+  until p=0;
+end;
+
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+  {Build the registernumber2regindex index.
+   Step 1: Fill.}
+  for i:=0 to regcount-1 do
+    gas_regname_index[i]:=i;
+  {Step 2: Sort. We use a Shell-Metzner sort.}
+  p:=regcount_bsstart;
+  repeat
+    for h:=0 to regcount-p-1 do
+      begin
+        i:=h;
+        repeat
+          j:=i+p;
+          if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+            break;
+          t:=gas_regname_index[i];
+          gas_regname_index[i]:=gas_regname_index[j];
+          gas_regname_index[j]:=t;
+          if i<p then
+            break;
+          dec(i,p);
+        until false;
+      end;
+    p:=p shr 1;
+  until p=0;
+end;
+
+
+procedure read_mipsreg_file;
+
+var infile:text;
+
+begin
+   { open dat file }
+   assign(infile,'mipsreg.dat');
+   reset(infile);
+   while not(eof(infile)) do
+     begin
+        { handle comment }
+        readln(infile,s);
+        inc(line);
+        while (s[1]=' ') do
+         delete(s,1,1);
+        if (s='') or (s[1]=';') then
+          continue;
+
+        i:=1;
+        names[regcount]:=readstr;
+        readcomma;
+        regtypes[regcount]:=readstr;
+        readcomma;
+        supregs[regcount]:=readstr;
+        readcomma;
+        stdnames[regcount]:=readstr;
+        readcomma;
+        gasnames[regcount]:=readstr;
+        readcomma;
+        stabs[regcount]:=readstr;
+        readcomma;
+        dwarfs[regcount]:=readstr;
+        { Create register number }
+        if supregs[regcount][1]<>'$' then
+          begin
+            writeln('Missing $ before number, at line ',line);
+            writeln('Line: "',s,'"');
+            halt(1);
+          end;
+        numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+        if i<length(s) then
+          begin
+            writeln('Extra chars at end of line, at line ',line);
+            writeln('Line: "',s,'"');
+            halt(1);
+          end;
+        inc(regcount);
+        if regcount>max_regcount then
+          begin
+            writeln('Error: Too much registers, please increase maxregcount in source');
+            halt(2);
+          end;
+     end;
+   close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+    norfile,stdfile,supfile,
+    numfile,stabfile,confile,gasfile,dwarffile,
+    rnifile,srifile,mrifile,grifile : text;
+    first:boolean;
+
+begin
+  { create inc files }
+  openinc(confile,'rmipscon.inc');
+  openinc(supfile,'rmipssup.inc');
+  openinc(numfile,'rmipsnum.inc');
+  openinc(stdfile,'rmipsstd.inc');
+  openinc(gasfile,'rmipsgas.inc');
+  openinc(stabfile,'rmipssta.inc');
+  openinc(dwarffile,'rmipsdwf.inc');
+  openinc(norfile,'rmipsnor.inc');
+  openinc(rnifile,'rmipsrni.inc');
+  openinc(srifile,'rmipssri.inc');
+  openinc(grifile,'rmipsgri.inc');
+  openinc(mrifile,'rmipsmri.inc');
+  first:=true;
+  for i:=0 to regcount-1 do
+    begin
+      if not first then
+        begin
+          writeln(numfile,',');
+          writeln(stdfile,',');
+          writeln(gasfile,',');
+          writeln(stabfile,',');
+          writeln(dwarffile,',');
+          writeln(rnifile,',');
+          writeln(srifile,',');
+          writeln(grifile,',');
+          writeln(mrifile,',');
+        end
+      else
+        first:=false;
+      writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+      writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+      write(numfile,'tregister(',numbers[i],')');
+      write(stdfile,'''',stdnames[i],'''');
+      write(gasfile,'''',gasnames[i],'''');
+      write(stabfile,stabs[i]);
+      write(dwarffile,dwarfs[i]);
+      write(rnifile,regnumber_index[i]);
+      write(srifile,std_regname_index[i]);
+      write(grifile,gas_regname_index[i]);
+      write(mrifile,mot_regname_index[i]);
+    end;
+  write(norfile,regcount);
+  close(confile);
+  close(supfile);
+  closeinc(numfile);
+  closeinc(stdfile);
+  closeinc(gasfile);
+  closeinc(stabfile);
+  closeinc(dwarffile);
+  closeinc(norfile);
+  closeinc(rnifile);
+  closeinc(srifile);
+  closeinc(grifile);
+  closeinc(mrifile);
+  writeln('Done!');
+  writeln(regcount,' registers procesed');
+end;
+
+
+begin
+   writeln('Register Table Converter Version ',Version);
+   line:=0;
+   regcount:=0;
+   read_mipsreg_file;
+   regcount_bsstart:=1;
+   while 2*regcount_bsstart<regcount do
+     regcount_bsstart:=regcount_bsstart*2;
+   build_regnum_index;
+   build_std_regname_index;
+   build_gas_regname_index;
+   write_inc_files;
+end.
+{
+  $Log$
+  Revision 1.1  2005-02-13 18:56:44  florian
+    + basic mips stuff
+}