Pārlūkot izejas kodu

* adapted more fpc-mips stuff to trunk

git-svn-id: trunk@14230 -
florian 15 gadi atpakaļ
vecāks
revīzija
f54365db94

+ 7 - 0
.gitattributes

@@ -244,9 +244,15 @@ compiler/mips/cpuinfo.pas svneol=native#text/plain
 compiler/mips/cpunode.pas svneol=native#text/plain
 compiler/mips/cpupara.pas svneol=native#text/plain
 compiler/mips/cpupi.pas svneol=native#text/plain
+compiler/mips/cputarg.pas svneol=native#text/pascal
 compiler/mips/itcpugas.pas svneol=native#text/plain
 compiler/mips/mipsreg.dat svneol=native#text/plain
 compiler/mips/ncpuadd.pas svneol=native#text/plain
+compiler/mips/ncpucall.pas svneol=native#text/pascal
+compiler/mips/ncpucnv.pas svneol=native#text/pascal
+compiler/mips/ncpuinln.pas svneol=native#text/pascal
+compiler/mips/ncpumat.pas svneol=native#text/pascal
+compiler/mips/ncpuset.pas svneol=native#text/pascal
 compiler/mips/opcode.inc svneol=native#text/plain
 compiler/mips/rgcpu.pas svneol=native#text/plain
 compiler/mips/rmipscon.inc svneol=native#text/plain
@@ -263,6 +269,7 @@ compiler/mips/rmipssri.inc svneol=native#text/plain
 compiler/mips/rmipssta.inc svneol=native#text/plain
 compiler/mips/rmipsstd.inc svneol=native#text/plain
 compiler/mips/rmipssup.inc svneol=native#text/plain
+compiler/mips/strinst.inc svneol=native#text/plain
 compiler/msg/errorct.msg svneol=native#text/plain
 compiler/msg/errord.msg svneol=native#text/plain
 compiler/msg/errorda.msg svneol=native#text/plain

+ 6 - 6
compiler/arm/agarmgas.pas

@@ -41,13 +41,13 @@ unit agarmgas;
         procedure WriteExtraHeader; override;
       end;
 
-     TArmInstrWriter=class(TCPUInstrWriter)
+      TArmInstrWriter=class(TCPUInstrWriter)
         procedure WriteInstruction(hp : tai);override;
-     end;
+      end;
 
-    TArmAppleGNUAssembler=class(TAppleGNUassembler)
-      constructor create(smart: boolean); override;
-    end;
+      TArmAppleGNUAssembler=class(TAppleGNUassembler)
+        constructor create(smart: boolean); override;
+      end;
 
 
     const
@@ -95,7 +95,7 @@ unit agarmgas;
       end;
 
 {****************************************************************************}
-{                      GNU/Apple PPC Assembler writer                        }
+{                      GNU/Apple ARM Assembler writer                        }
 {****************************************************************************}
 
     constructor TArmAppleGNUAssembler.create(smart: boolean);

+ 220 - 201
compiler/mips/cpugas.pas

@@ -23,224 +23,243 @@ unit cpugas;
 
 {$i fpcdefs.inc}
 
-interface
+  interface
 
-uses
-  cpubase,
-  aasmtai, aasmcpu, assemble, aggas;
+    uses
+      cpubase,
+       aasmtai, aasmcpu, assemble, aggas;
 
-type
-  TGasMIPSEL = class(TGnuAssembler)
-    procedure WriteInstruction(hp: Tai); override;
-  end;
+    type
+      TMIPSGNUAssembler = class(TGNUassembler)
+        constructor create(smart: boolean); override;
+      end;
+
+      TMIPSInstrWriter = class(TCPUInstrWriter)
+        procedure WriteInstruction(hp : tai);override;
+      end;
 
-implementation
+  implementation
 
-uses
-  cutils, systems,
-  verbose, itcpugas, cgbase, cgutils;
+    uses
+      cutils, systems,
+      verbose, itcpugas, cgbase, cgutils;
 
-function GetReferenceString(var ref: TReference): string;
-begin
-  GetReferenceString := '';
-  with ref do
-  begin
-    if (base = NR_NO) and (index = NR_NO) then
-    begin
-      if assigned(symbol) then
-        GetReferenceString := symbol.Name;
-      if offset > 0 then
-        GetReferenceString := GetReferenceString + '+' + ToStr(offset)
-      else if offset < 0 then
-        GetReferenceString := GetReferenceString + ToStr(offset);
-      case refaddr of
-        addr_hi:
-          GetReferenceString := '%hi(' + GetReferenceString + ')';
-        addr_lo:
-          GetReferenceString := '%lo(' + GetReferenceString + ')';
+{****************************************************************************}
+{                         GNU MIPS  Assembler writer                           }
+{****************************************************************************}
+
+    constructor TMIPSGNUAssembler.create(smart: boolean);
+      begin
+        inherited create(smart);
+        InstrWriter := TMIPSInstrWriter.create(self);
       end;
-    end
-    else
-    begin
-{$ifdef extdebug}
-      if assigned(symbol) and
-        not(refaddr in [addr_pic,addr_lo]) then
-        internalerror(2003052601);
-{$endif extdebug}
-      if base <> NR_NO then
-        GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
-      if index = NR_NO then
+
+
+{****************************************************************************}
+{                  Helper routines for Instruction Writer                    }
+{****************************************************************************}
+
+    function GetReferenceString(var ref: TReference): string;
       begin
-        if offset <> 0 then
-          GetReferenceString := ToStr(offset) + GetReferenceString;
-        if assigned(symbol) then
+        GetReferenceString := '';
+        with ref do
         begin
-          if refaddr = addr_lo then
-            GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
+          if (base = NR_NO) and (index = NR_NO) then
+          begin
+            if assigned(symbol) then
+              GetReferenceString := symbol.Name;
+            if offset > 0 then
+              GetReferenceString := GetReferenceString + '+' + ToStr(offset)
+            else if offset < 0 then
+              GetReferenceString := GetReferenceString + ToStr(offset);
+            case refaddr of
+              addr_high:
+                GetReferenceString := '%hi(' + GetReferenceString + ')';
+              addr_low:
+                GetReferenceString := '%lo(' + GetReferenceString + ')';
+            end;
+          end
           else
-            GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
-        end;
-      end
-      else
-      begin
-{$ifdef extdebug}
-                    if (Offset<>0) or assigned(symbol) then
-                      internalerror(2003052603);
-{$endif extdebug}
-        GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
+          begin
+      {$ifdef extdebug}
+            if assigned(symbol) and
+              not(refaddr in [addr_pic,addr_lo]) then
+              internalerror(2003052601);
+      {$endif extdebug}
+            if base <> NR_NO then
+              GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
+            if index = NR_NO then
+            begin
+              if offset <> 0 then
+                GetReferenceString := ToStr(offset) + GetReferenceString;
+              if assigned(symbol) then
+              begin
+                if refaddr = addr_low then
+                  GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
+                else
+                  GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
+              end;
+            end
+            else
+            begin
+  {$ifdef extdebug}
+              if (Offset<>0) or assigned(symbol) then
+                internalerror(2003052603);
+  {$endif extdebug}
+              GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
 
+            end;
+          end;
+        end;
       end;
-    end;
-  end;
-end;
 
 
-function getopstr(const Oper: TOper): string;
-begin
-  with Oper do
-    case typ of
-      top_reg:
-        getopstr := gas_regname(reg);
-      top_const:
-        getopstr := tostr(longint(val));
-      top_ref:
-        if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_lo) and ((oper.ref^.base <> NR_NO) or
-          (oper.ref^.index <> NR_NO))) then
-          getopstr := getreferencestring(ref^)
-        else
-          getopstr := getreferencestring(ref^);
-      else
-        internalerror(10001);
-    end;
-end;
-
-function getopstr_4(const Oper: TOper): string;
-var
-  tmpref: treference;
-begin
-  with Oper do
-    case typ of
-      top_ref:
+    function getopstr(const Oper: TOper): string;
       begin
-        tmpref := ref^;
-        Inc(tmpref.offset, 4);
-        getopstr_4 := getreferencestring(tmpref);
+        with Oper do
+          case typ of
+            top_reg:
+              getopstr := gas_regname(reg);
+            top_const:
+              getopstr := tostr(longint(val));
+            top_ref:
+              if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_low) and ((oper.ref^.base <> NR_NO) or
+                (oper.ref^.index <> NR_NO))) then
+                getopstr := getreferencestring(ref^)
+              else
+                getopstr := getreferencestring(ref^);
+            else
+              internalerror(10001);
+          end;
       end;
-      else
-        internalerror(2007050403);
-    end;
-end;
-
-
-procedure TGasMIPSEL.WriteInstruction(hp: Tai);
-var
-  Op: TAsmOp;
-  s,s1:  string;
-  i:  integer;
-  tmpfpu: string;
-  tmpfpu_len: longint;
-begin
-  if hp.typ <> ait_instruction then
-    exit;
-  op := taicpu(hp).opcode;
-
-  case op of
-    A_P_STK2:
-    begin
-      s1 := getopstr(taicpu(hp).oper[2]^);
-      STK2_LocalSize := align(STK2_LocalSize, 8);
-      if s1[1] = '-' then
-        str(-STK2_LocalSize, s1)
-      else
-        str(STK2_LocalSize, s1);
-      s := #9 + std_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
-      AsmWriteLn(s);
-    end;
-    A_P_FRAME:
-    begin
-    end;
-    A_P_SET_MACRO:
-    begin
-      s := #9 + '.set' + #9 + 'macro';
-      AsmWriteLn(s);
-    end;
-    A_P_SET_REORDER:
-    begin
-      s := #9 + '.set' + #9 + 'reorder';
-      AsmWriteLn(s);
-    end;
-    A_P_SET_NOMACRO:
-    begin
-      s := #9 + '.set' + #9 + 'nomacro';
-      AsmWriteLn(s);
-    end;
-    A_P_SET_NOREORDER:
-    begin
-      s := #9 + '.set' + #9 + 'noreorder';
-      AsmWriteLn(s);
-    end;
-    A_P_SW:
-    begin
-      s := #9 + std_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
-      AsmWriteLn(s);
-    end;
-    A_P_LW:
-    begin
-      s := #9 + std_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
-      AsmWriteLn(s);
-    end;
-    A_LDC1:
-    begin
-      tmpfpu := getopstr(taicpu(hp).oper[0]^);
-      s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
-      AsmWriteLn(s);
-
-      tmpfpu_len := length(tmpfpu);
-      tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
-      s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
-      AsmWriteLn(s);
-    end;
-    A_SDC1:
-    begin
-      tmpfpu := getopstr(taicpu(hp).oper[0]^);
-      s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
-      AsmWriteLn(s);
-
-      tmpfpu_len := length(tmpfpu);
-      tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
-      s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
-      AsmWriteLn(s);
-    end;
-    else
-    begin
-      s := #9 + std_op2str[op] + cond2str[taicpu(hp).condition];
-      if taicpu(hp).delayslot_annulled then
-        s := s + ',a';
-      if taicpu(hp).ops > 0 then
+
+      function getopstr_4(const Oper: TOper): string;
+      var
+        tmpref: treference;
       begin
-        s := s + #9 + getopstr(taicpu(hp).oper[0]^);
-        for i := 1 to taicpu(hp).ops - 1 do
-          s := s + ',' + getopstr(taicpu(hp).oper[i]^);
+        with Oper do
+          case typ of
+            top_ref:
+            begin
+              tmpref := ref^;
+              Inc(tmpref.offset, 4);
+              getopstr_4 := getreferencestring(tmpref);
+            end;
+            else
+              internalerror(2007050403);
+          end;
       end;
-      AsmWriteLn(s);
-    end;
-  end;
-end;
-
-
-const
-  as_MIPSEL_as_info: tasminfo =
-    (
-    id: as_gas;
-    idtxt: 'AS';
-    asmbin: 'as';
-    asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
-    supported_target: system_any;
-    flags: [af_allowdirect, af_needar, af_smartlink_sections];
-    labelprefix: '.L';
-    comment: '# ';
-    );
+
+
+    procedure TMIPSInstrWriter.WriteInstruction(hp: Tai);
+      var
+        Op: TAsmOp;
+        s,s1:  string;
+        i:  integer;
+        tmpfpu: string;
+        tmpfpu_len: longint;
+      begin
+        if hp.typ <> ait_instruction then
+          exit;
+        op := taicpu(hp).opcode;
+
+        case op of
+          A_P_STK2:
+          begin
+            s1 := getopstr(taicpu(hp).oper[2]^);
+            STK2_LocalSize := align(STK2_LocalSize, 8);
+            if s1[1] = '-' then
+              str(-STK2_LocalSize, s1)
+            else
+              str(STK2_LocalSize, s1);
+            s := #9 + gas_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
+            owner.AsmWriteLn(s);
+          end;
+          A_P_FRAME:
+          begin
+          end;
+          A_P_SET_MACRO:
+          begin
+            s := #9 + '.set' + #9 + 'macro';
+            owner.AsmWriteLn(s);
+          end;
+          A_P_SET_REORDER:
+          begin
+            s := #9 + '.set' + #9 + 'reorder';
+            owner.AsmWriteLn(s);
+          end;
+          A_P_SET_NOMACRO:
+          begin
+            s := #9 + '.set' + #9 + 'nomacro';
+            owner.AsmWriteLn(s);
+          end;
+          A_P_SET_NOREORDER:
+          begin
+            s := #9 + '.set' + #9 + 'noreorder';
+            owner.AsmWriteLn(s);
+          end;
+          A_P_SW:
+          begin
+            s := #9 + gas_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+            owner.AsmWriteLn(s);
+          end;
+          A_P_LW:
+          begin
+            s := #9 + gas_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+            owner.AsmWriteLn(s);
+          end;
+          A_LDC1:
+          begin
+            tmpfpu := getopstr(taicpu(hp).oper[0]^);
+            s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+            owner.AsmWriteLn(s);
+
+            tmpfpu_len := length(tmpfpu);
+            tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
+            s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+            owner.AsmWriteLn(s);
+          end;
+          A_SDC1:
+          begin
+            tmpfpu := getopstr(taicpu(hp).oper[0]^);
+            s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+            owner.AsmWriteLn(s);
+
+            tmpfpu_len := length(tmpfpu);
+            tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
+            s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+            owner.AsmWriteLn(s);
+          end;
+          else
+          begin
+            s := #9 + gas_op2str[op] + cond2str[taicpu(hp).condition];
+            if taicpu(hp).delayslot_annulled then
+              s := s + ',a';
+            if taicpu(hp).ops > 0 then
+            begin
+              s := s + #9 + getopstr(taicpu(hp).oper[0]^);
+              for i := 1 to taicpu(hp).ops - 1 do
+                s := s + ',' + getopstr(taicpu(hp).oper[i]^);
+            end;
+            owner.AsmWriteLn(s);
+          end;
+        end;
+      end;
+
+
+    const
+      as_MIPSEL_as_info: tasminfo =
+        (
+        id: as_gas;
+        idtxt: 'AS';
+        asmbin: 'as';
+        asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
+        supported_targets: [system_mips_linux];
+        flags: [af_allowdirect, af_needar, af_smartlink_sections];
+        labelprefix: '.L';
+        comment: '# ';
+        );
 
 begin
-  RegisterAssembler(as_MIPSEL_as_info, TGasMIPSEL);
+  RegisterAssembler(as_MIPSEL_as_info, TMIPSGNUAssembler);
 end.

+ 57 - 0
compiler/mips/cputarg.pas

@@ -0,0 +1,57 @@
+{
+    Copyright (c) 2001 by Peter Vreman
+
+    Includes the i386 dependent target units
+
+    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 cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+    uses
+      systems { prevent a syntax error when nothing is included }
+
+{$ifndef NOOPT}
+      ,aoptcpu
+{$endif NOOPT}
+
+{**************************************
+             Targets
+**************************************}
+
+    {$ifndef NOTARGETLINUX}
+      ,t_linux
+    {$endif}
+    {$ifndef NOTARGETSUNOS}
+      ,t_sunos
+    {$endif}
+
+{**************************************
+             Assemblers
+**************************************}
+
+      ,CpuGas
+
+      ;
+
+end.

+ 66 - 81
compiler/mips/itcpugas.pas

@@ -1,5 +1,5 @@
 {
-    Copyright (c) 1998-2005 by Florian Klaempfl
+    Copyright (c) 1998-2009 by Mazen NEIFER and David Zhang
 
     This unit contains the MIPS GAS instruction tables
 
@@ -25,92 +25,77 @@ unit itcpugas;
 
 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;
+uses
+  cpubase, cgbase;
+
+const
+  gas_op2str: array[tasmop] of string[14] = ({$INCLUDE strinst.inc});
+
+function gas_regnum_search(const s: string): Tregister;
+function gas_regname(r: Tregister): string;
 
 
 implementation
 
-    uses
-      cutils,verbose;
+uses
+  cutils, verbose;
 
-    const
-      gas_regname_table : array[tregisterindex] of string[7] = (
-        {$i rmipsgas.inc}
-      );
+const
+  gas_regname_table: array[tregisterindex] of string[7] = (
+        {$i rmipsstd.inc}
+    );
 
-      gas_regname_index : array[tregisterindex] of tregisterindex = (
+  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;
+    );
+
+
+function findreg_by_gasname(const s: string): tregisterindex;
+var
+  i, p: tregisterindex;
+begin
+  for p := low(tregisterindex) to high(tregisterindex) do
+  begin
+    if gas_regname_table[gas_regname_index[p]] = s then
+    begin
+      findreg_by_gasname := gas_regname_index[p];
+      exit
+    end;
+  end;
+  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
+  hr: tregister;
+  p:  longint;
+begin
+  { Double uses the same table as single }
+  hr := r;
+  case getsubreg(hr) of
+    R_SUBFD:
+      setsubreg(hr, R_SUBFS);
+    R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
+      setsubreg(hr, R_SUBD);
+  end;
+  p := findreg_by_number(hr);
+  if p <> 0 then
+    Result := gas_regname_table[p]
+  else
+    Result := generic_regname(r);
+end;
 
 end.
+{
+  $Log: itcpugas.pas,v $
+  Revision 1.7  2005/02/14 17:13:10  peter
+    * truncate log
+
+}

+ 16 - 16
compiler/mips/ncpuadd.pas

@@ -135,7 +135,7 @@ var
   lfcmp64_L4: tasmlabel;
 begin
 
-  objectlibrary.getlabel(lfcmp64_L4);
+  current_asmdata.getjumplabel(lfcmp64_L4);
 
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
 
@@ -155,7 +155,7 @@ var
   lfcmp64_L4: tasmlabel;
 begin
 
-  objectlibrary.getlabel(lfcmp64_L4);
+  current_asmdata.getjumplabel(lfcmp64_L4);
 
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
 
@@ -176,8 +176,8 @@ var
 begin
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
 
-  objectlibrary.getlabel(lfcmp64_L4);
-  objectlibrary.getlabel(lfcmp64_L5);
+  current_asmdata.getjumplabel(lfcmp64_L4);
+  current_asmdata.getjumplabel(lfcmp64_L5);
 
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, left_reg.reghi, right_reg.reghi));
   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
@@ -203,8 +203,8 @@ var
 begin
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
 
-  objectlibrary.getlabel(lfcmp64_L4);
-  objectlibrary.getlabel(lfcmp64_L5);
+  current_asmdata.getjumplabel(lfcmp64_L4);
+  current_asmdata.getjumplabel(lfcmp64_L5);
 
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, right_reg.reghi, left_reg.reghi));
   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
@@ -228,8 +228,8 @@ var
 begin
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
 
-  objectlibrary.getlabel(lfcmp64_L4);
-  objectlibrary.getlabel(lfcmp64_L5);
+  current_asmdata.getjumplabel(lfcmp64_L4);
+  current_asmdata.getjumplabel(lfcmp64_L5);
 
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reghi, right_reg.reghi));
   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
@@ -255,8 +255,8 @@ var
 begin
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
 
-  objectlibrary.getlabel(lfcmp64_L4);
-  objectlibrary.getlabel(lfcmp64_L5);
+  current_asmdata.getjumplabel(lfcmp64_L4);
+  current_asmdata.getjumplabel(lfcmp64_L5);
 
   current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reghi, left_reg.reghi));
   current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
@@ -422,7 +422,7 @@ begin
         op := A_C_EQ_D
       else
         op := A_C_EQ_S;
-      objectlibrary.getlabel(lfcmpfalse);
+      current_asmdata.getjumplabel(lfcmpfalse);
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse)); //lfcmpfalse
@@ -437,7 +437,7 @@ begin
         op := A_C_EQ_D
       else
         op := A_C_EQ_S;
-      objectlibrary.getlabel(lfcmpfalse);
+      current_asmdata.getjumplabel(lfcmpfalse);
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse));
@@ -451,7 +451,7 @@ begin
         op := A_C_LT_D
       else
         op := A_C_LT_S;
-      objectlibrary.getlabel(lfcmptrue);
+      current_asmdata.getjumplabel(lfcmptrue);
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
@@ -465,7 +465,7 @@ begin
         op := A_C_LE_D
       else
         op := A_C_LE_S;
-      objectlibrary.getlabel(lfcmptrue);
+      current_asmdata.getjumplabel(lfcmptrue);
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
@@ -479,7 +479,7 @@ begin
         op := A_C_LT_D
       else
         op := A_C_LT_S;
-      objectlibrary.getlabel(lfcmptrue);
+      current_asmdata.getjumplabel(lfcmptrue);
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
@@ -493,7 +493,7 @@ begin
         op := A_C_LE_D
       else
         op := A_C_LE_S;
-      objectlibrary.getlabel(lfcmptrue);
+      current_asmdata.getjumplabel(lfcmptrue);
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
       current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));

+ 62 - 0
compiler/mips/ncpucall.pas

@@ -0,0 +1,62 @@
+{
+    Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
+
+    Generate MIPSEL assembler for in call nodes
+
+    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 ncpucall;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  ncgcal;
+
+type
+  tMIPSELcallnode = class(tcgcallnode)
+    procedure extra_call_code; override;
+    procedure extra_post_call_code; override;
+  end;
+
+
+implementation
+
+uses
+  cpubase,
+  aasmtai,aasmcpu,aasmdata,
+  paramgr,
+  ncal;
+
+procedure tMIPSELcallnode.extra_call_code;
+begin
+  if pushedparasize > 0 then
+    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, -pushedparasize));
+end;
+
+procedure tMIPSELcallnode.extra_post_call_code;
+begin
+  if pushedparasize > 0 then
+    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, pushedparasize));
+
+end;
+
+
+begin
+  ccallnode := TMIPSELCallNode;
+end.

+ 285 - 0
compiler/mips/ncpucnv.pas

@@ -0,0 +1,285 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl and David Zhang
+
+    Generate MIPSEL assembler for type converting nodes
+
+    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 ncpucnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  node, ncnv, ncgcnv, defcmp;
+
+type
+  tMIPSELtypeconvnode = class(TCgTypeConvNode)
+  protected
+    { procedure second_int_to_int;override; }
+    { procedure second_string_to_string;override; }
+    { procedure second_cstring_to_pchar;override; }
+    { procedure second_string_to_chararray;override; }
+    { procedure second_array_to_pointer;override; }
+    function first_int_to_real: tnode; override;
+    { procedure second_pointer_to_array;override; }
+    { procedure second_chararray_to_string;override; }
+    { procedure second_char_to_string;override; }
+    procedure second_int_to_real; override;
+    procedure second_real_to_real; override;
+    { procedure second_cord_to_pointer;override; }
+    { procedure second_proc_to_procvar;override; }
+    { procedure second_bool_to_int;override; }
+    procedure second_int_to_bool; override;
+    { procedure second_load_smallset;override;  }
+    { procedure second_ansistring_to_pchar;override; }
+    { procedure second_pchar_to_string;override; }
+    { procedure second_class_to_intf;override; }
+    { procedure second_char_to_char;override; }
+  end;
+
+implementation
+
+uses
+  verbose, globtype, globals, systems,
+  symconst, symdef, aasmbase, aasmtai, aasmdata,
+  defutil,
+  cgbase, cgutils, pass_1, pass_2, procinfo,
+  ncon, ncal,
+  ncgutil,
+  cpubase, aasmcpu,
+  tgobj, cgobj;
+
+
+{*****************************************************************************
+                             FirstTypeConv
+*****************************************************************************}
+
+function tMIPSELtypeconvnode.first_int_to_real: tnode;
+var
+  fname: string[19];
+begin
+  { converting a 64bit integer to a float requires a helper }
+  if is_64bitint(left.resultdef) or
+    is_currency(left.resultdef) then
+  begin
+            { hack to avoid double division by 10000, as it's
+              already done by resulttypepass.resulttype_int_to_real }
+    if is_currency(left.resultdef) then
+      left.resultdef := s64inttype;
+    if is_signed(left.resultdef) then
+      fname := 'fpc_int64_to_double'
+    else
+      fname := 'fpc_qword_to_double';
+    Result := ccallnode.createintern(fname, ccallparanode.Create(
+      left, nil));
+    left := nil;
+    firstpass(Result);
+    exit;
+  end
+  else
+    { other integers are supposed to be 32 bit }
+  begin
+    if is_signed(left.resultdef) then
+      inserttypeconv(left, s32inttype)
+    else
+      inserttypeconv(left, u32inttype);
+    firstpass(left);
+  end;
+  Result := nil;
+  expectloc := LOC_FPUREGISTER;
+end;
+
+
+{*****************************************************************************
+                             SecondTypeConv
+*****************************************************************************}
+
+procedure tMIPSELtypeconvnode.second_int_to_real;
+
+  procedure loadsigned;
+  begin
+    location_force_mem(current_asmdata.CurrAsmList, left.location);
+    location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+    { Load memory in fpu register }
+    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F32, OS_F32, left.location.reference, location.Register);
+    tg.ungetiftemp(current_asmdata.CurrAsmList, left.location.reference);
+    { Convert value in fpu register from integer to float }
+    case tfloatdef(resultdef).floattype of
+      s32real:
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_S_W, location.Register, location.Register));
+      s64real:
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_D_W, location.Register, location.Register));
+      else
+        internalerror(200408011);
+    end;
+  end;
+
+var
+  href:      treference;
+  hregister: tregister;
+  l1, l2:    tasmlabel;
+
+begin
+  location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+  if is_signed(left.resultdef) then
+    loadsigned
+  else
+  begin
+    current_asmdata.getdatalabel(l1);
+    current_asmdata.getjumplabel(l2);
+    reference_reset_symbol(href, l1, 0, sizeof(aint));
+    hregister := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
+    cg.a_load_loc_reg(current_asmdata.CurrAsmList, OS_32, left.location, hregister);
+
+    loadsigned;
+
+    current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BGE, hregister, NR_R0, l2));
+
+    case tfloatdef(resultdef).floattype of
+      { converting dword to s64real first and cut off at the end avoids precision loss }
+      s32real,
+      s64real:
+      begin
+        hregister := cg.getfpuregister(current_asmdata.CurrAsmList, OS_F64);
+        current_asmdata.asmlists[al_typedconsts].concat(tai_align.Create(const_align(8)));
+        current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+
+        { I got this constant from a test program (FK) }
+        current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+        current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($0000f041));
+
+        cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F64, OS_F64, href, hregister);
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADD_D, location.Register, hregister, location.Register));
+        cg.a_label(current_asmdata.CurrAsmList, l2);
+
+        { cut off if we should convert to single }
+        if tfloatdef(resultdef).floattype = s32real then
+        begin
+          hregister := location.Register;
+          location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_S_D, location.Register, hregister));
+        end;
+      end;
+      else
+        internalerror(200410031);
+    end;
+  end;
+end;
+
+
+procedure tMIPSELtypeconvnode.second_real_to_real;
+const
+  conv_op: array[tfloattype, tfloattype] of tasmop = (
+    {    from:   s32      s64         s80     c64     cur    f128 }
+    { s32 }  (A_MOV_S,   A_CVT_S_D, A_NONE, A_NONE, A_NONE, A_NONE),
+    { s64 }  (A_CVT_D_S, A_MOV_D,   A_NONE, A_NONE, A_NONE, A_NONE),
+    { s80 }  (A_NONE,    A_NONE,    A_NONE, A_NONE, A_NONE, A_NONE),
+    { c64 }  (A_NONE,    A_NONE,    A_NONE, A_NONE, A_NONE, A_NONE),
+    { cur }  (A_NONE,    A_NONE,    A_NONE, A_NONE, A_NONE, A_NONE),
+    { f128 } (A_NONE,    A_NONE,    A_NONE, A_NONE, A_NONE, A_NONE)
+    );
+var
+  op: tasmop;
+begin
+  location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+  location_force_fpureg(current_asmdata.CurrAsmList, left.location, False);
+  { Convert value in fpu register from integer to float }
+  op := conv_op[tfloatdef(resultdef).floattype, tfloatdef(left.resultdef).floattype];
+  if op = A_NONE then
+    internalerror(200401121);
+  location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+  current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, location.Register, left.location.Register));
+end;
+
+
+procedure tMIPSELtypeconvnode.second_int_to_bool;
+var
+  hreg1, hreg2: tregister;
+  opsize: tcgsize;
+  hlabel, oldtruelabel, oldfalselabel: tasmlabel;
+begin
+  oldtruelabel  := current_procinfo.CurrTrueLabel;
+  oldfalselabel := current_procinfo.CurrFalseLabel;
+  current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+  current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+  secondpass(left);
+  if codegenerror then
+    exit;
+
+  { byte(boolean) or word(wordbool) or longint(longbool) must }
+  { be accepted for var parameters                            }
+  if (nf_explicit in flags) and
+    (left.resultdef.size = resultdef.size) and
+    (left.location.loc in [LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER]) then
+  begin
+    location_copy(location, left.location);
+    current_procinfo.CurrTrueLabel  := oldtruelabel;
+    current_procinfo.CurrFalseLabel := oldfalselabel;
+    exit;
+  end;
+  location_reset(location, LOC_REGISTER, def_cgsize(resultdef));
+  opsize := def_cgsize(left.resultdef);
+  case left.location.loc of
+    LOC_CREFERENCE, LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER:
+    begin
+      if left.location.loc in [LOC_CREFERENCE, LOC_REFERENCE] then
+      begin
+        hreg2 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+        cg.a_load_ref_reg(current_asmdata.CurrAsmList, opsize, opsize, left.location.reference, hreg2);
+      end
+      else
+        hreg2 := left.location.Register;
+{$ifndef cpu64bit}
+      if left.location.size in [OS_64, OS_S64] then
+      begin
+        hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
+        cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hreg2, tregister(succ(longint(hreg2))), hreg1);
+        hreg2  := hreg1;
+        opsize := OS_32;
+      end;
+{$endif cpu64bit}
+      hreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SNE, hreg1, hreg2, NR_R0));
+    end;
+    LOC_JUMP:
+    begin
+      hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+      current_asmdata.getjumplabel(hlabel);
+      cg.a_label(current_asmdata.CurrAsmList, current_procinfo.CurrTrueLabel);
+      cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 1, hreg1);
+      cg.a_jmp_always(current_asmdata.CurrAsmList, hlabel);
+      cg.a_label(current_asmdata.CurrAsmList, current_procinfo.CurrFalseLabel);
+      cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, hreg1);
+      cg.a_label(current_asmdata.CurrAsmList, hlabel);
+    end;
+    else
+      internalerror(10062);
+  end;
+  location.Register := hreg1;
+
+  if location.size in [OS_64, OS_S64] then
+    internalerror(200408241);
+
+  current_procinfo.CurrTrueLabel  := oldtruelabel;
+  current_procinfo.CurrFalseLabel := oldfalselabel;
+end;
+
+
+begin
+  ctypeconvnode := tMIPSELtypeconvnode;
+end.

+ 138 - 0
compiler/mips/ncpuinln.pas

@@ -0,0 +1,138 @@
+{
+    Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
+
+    Generate MIPSEL inline nodes
+
+    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 ncpuinln;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  node, ninl, ncginl;
+
+type
+  tMIPSELinlinenode = class(tcgInlineNode)
+    function first_abs_real: tnode; override;
+    function first_sqr_real: tnode; override;
+    function first_sqrt_real: tnode; override;
+    procedure second_abs_real; override;
+    procedure second_sqr_real; override;
+    procedure second_sqrt_real; override;
+  private
+    procedure load_fpu_location;
+  end;
+
+
+implementation
+
+uses
+  systems,
+  globtype,
+  cutils, verbose,
+  symconst, symdef,
+  aasmtai, aasmcpu, aasmdata,
+  cgbase, pass_2,
+  cpubase, paramgr,
+  nbas, ncon, ncal, ncnv, nld,
+  ncgutil, cgobj, cgutils;
+
+{*****************************************************************************
+                              tMIPSELinlinenode
+*****************************************************************************}
+
+procedure tMIPSELinlinenode.load_fpu_location;
+begin
+  secondpass(left);
+  location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
+  location_copy(location, left.location);
+  if left.location.loc = LOC_CFPUREGISTER then
+  begin
+    location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+    location.loc      := LOC_FPUREGISTER;
+  end;
+end;
+
+
+function tMIPSELinlinenode.first_abs_real: tnode;
+begin
+  expectloc      := LOC_FPUREGISTER;
+  first_abs_real := nil;
+end;
+
+
+function tMIPSELinlinenode.first_sqr_real: tnode;
+begin
+  expectloc      := LOC_FPUREGISTER;
+  first_sqr_real := nil;
+end;
+
+
+function tMIPSELinlinenode.first_sqrt_real: tnode;
+begin
+  expectloc    := LOC_FPUREGISTER;
+  first_sqrt_real := nil;
+end;
+
+
+procedure tMIPSELinlinenode.second_abs_real;
+begin
+  load_fpu_location;
+  case tfloatdef(left.resultdef).floattype of
+    s32real:
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ABS_s, location.Register, left.location.Register));
+    s64real:
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ABS_d, location.Register, left.location.Register));
+    else
+      internalerror(200410031);
+  end;
+end;
+
+
+procedure tMIPSELinlinenode.second_sqr_real;
+begin
+  load_fpu_location;
+  case tfloatdef(left.resultdef).floattype of
+    s32real:
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MUL_s, location.Register, left.location.Register, left.location.Register));
+    s64real:
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MUL_d, location.Register, left.location.Register, left.location.Register));
+    else
+      internalerror(200410032);
+  end;
+end;
+
+
+procedure tMIPSELinlinenode.second_sqrt_real;
+begin
+  load_fpu_location;
+  case tfloatdef(left.resultdef).floattype of
+    s32real:
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRT_s, location.Register, left.location.Register));
+    s64real:
+      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRT_d, location.Register, left.location.Register));
+    else
+      internalerror(200410033);
+  end;
+end;
+
+begin
+  cInlineNode := tMIPSELinlinenode;
+end.

+ 302 - 0
compiler/mips/ncpumat.pas

@@ -0,0 +1,302 @@
+{
+David Zhang 2007/01/15
+    $Id: ncpumat.pas,v 1.23 2005/02/14 17:13:10 peter Exp $
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate MIPSel assembler for math nodes
+
+    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 ncpumat;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  node, nmat, ncgmat;
+
+type
+  tMIPSELmoddivnode = class(tmoddivnode)
+    procedure pass_generate_code;override;
+  end;
+
+  tMIPSELshlshrnode = class(tshlshrnode)
+    procedure pass_generate_code;override;
+    { everything will be handled in pass_2 }
+    function first_shlshr64bitint: tnode; override;
+  end;
+
+  tMIPSELnotnode = class(tcgnotnode)
+    procedure second_boolean; override;
+  end;
+
+implementation
+
+uses
+  globtype, systems,
+  cutils, verbose, globals,
+  symconst,
+  aasmbase, aasmcpu, aasmtai, aasmdata,
+  defutil,
+  procinfo,
+  cgbase, cgobj, pass_2,
+  ncon,
+  cpubase,
+  ncgutil, cgcpu, cgutils;
+
+{*****************************************************************************
+                             TMipselMODDIVNODE
+*****************************************************************************}
+
+procedure tMIPSELmoddivnode.pass_generate_code;
+var
+  power: longint;
+  tmpreg, numerator, divider, resultreg: tregister;
+begin
+  secondpass(left);
+  secondpass(right);
+  location_copy(location, left.location);
+
+  { put numerator in register }
+  location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
+  location_copy(location, left.location);
+  numerator := location.Register;
+
+  if (nodetype = modn) then
+    resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT)
+  else
+  begin
+    if (location.loc = LOC_CREGISTER) then
+    begin
+      location.loc      := LOC_REGISTER;
+      location.Register := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+    end;
+    resultreg := location.Register;
+  end;
+
+  if (nodetype = divn) and
+    (right.nodetype = ordconstn) and
+    ispowerof2(tordconstnode(right).Value.svalue, power) then
+  begin
+    tmpreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+    cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, tmpreg);
+    { if signed, tmpreg=right value-1, otherwise 0 }
+    cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).Value.svalue - 1, tmpreg);
+    { add to the left value }
+    cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, tmpreg, numerator);
+    cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, aword(power), numerator, resultreg);
+  end
+  else
+  begin
+    { load divider in a register if necessary }
+    location_force_reg(current_asmdata.CurrAsmList, right.location,
+      def_cgsize(right.resultdef), True);
+    divider := right.location.Register;
+
+
+    if (nodetype = modn) then
+    begin
+      if is_signed(right.resultdef) then
+      begin
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_REM, resultreg, numerator, divider));
+      end
+      else
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_REMU, resultreg, numerator, divider));
+    end
+    else
+    begin
+      if is_signed({left.resultdef}right.resultdef) then
+      begin
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIV, resultreg, numerator, divider));
+      end
+      else
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIVU, resultreg, numerator, divider));
+    end;
+  end;
+  { set result location }
+  location.loc      := LOC_REGISTER;
+  location.Register := resultreg;
+end;
+
+
+{*****************************************************************************
+                             TMIPSelSHLRSHRNODE
+*****************************************************************************}
+
+function TMIPSELShlShrNode.first_shlshr64bitint: TNode;
+begin
+  { 64bit without constants need a helper }
+  if is_64bit(left.resultdef) and
+    (right.nodetype <> ordconstn) then
+  begin
+    Result := inherited first_shlshr64bitint;
+    exit;
+  end;
+
+  Result := nil;
+end;
+
+
+procedure tMIPSELshlshrnode.pass_generate_code;
+var
+  hregister, resultreg, hregister1, hreg64hi, hreg64lo: tregister;
+  op: topcg;
+  shiftval: aword;
+begin
+  { 64bit without constants need a helper, and is
+          already replaced in pass1 }
+  if is_64bit(left.resultdef) and
+    (right.nodetype <> ordconstn) then
+    internalerror(200405301);
+
+  secondpass(left);
+  secondpass(right);
+  if is_64bit(left.resultdef) then
+  begin
+    location_reset(location, LOC_REGISTER, OS_64);
+
+    { load left operator in a register }
+    location_force_reg(current_asmdata.CurrAsmList, left.location, OS_64, False);
+
+
+    hreg64hi := left.location.register64.reghi;
+    hreg64lo := left.location.register64.reglo;
+
+    shiftval := tordconstnode(right).Value.svalue and 63;
+    if shiftval > 31 then
+    begin
+      if nodetype = shln then
+      begin
+        cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_32, 0, hreg64hi);
+        if (shiftval and 31) <> 0 then
+          cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval and 31, hreg64lo, hreg64lo);
+      end
+      else
+      begin
+        cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_32, 0, hreg64lo);
+        if (shiftval and 31) <> 0 then
+          cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval and 31, hreg64hi, hreg64hi);
+      end;
+      location.register64.reglo := hreg64hi;
+      location.register64.reghi := hreg64lo;
+    end
+    else
+    begin
+      hregister := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
+      if nodetype = shln then
+      begin
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, 32 - shiftval, hreg64lo, hregister);
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval, hreg64hi, hreg64hi);
+        cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hregister, hreg64hi, hreg64hi);
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval, hreg64lo, hreg64lo);
+      end
+      else
+      begin
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, 32 - shiftval, hreg64hi, hregister);
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval, hreg64lo, hreg64lo);
+        cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hregister, hreg64lo, hreg64lo);
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval, hreg64hi, hreg64hi);
+      end;
+      location.register64.reghi := hreg64hi;
+      location.register64.reglo := hreg64lo;
+    end;
+  end
+  else
+  begin
+    { load left operators in a register }
+    location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
+    location_copy(location, left.location);
+    resultreg  := location.Register;
+    hregister1 := location.Register;
+    if (location.loc = LOC_CREGISTER) then
+    begin
+      location.loc := LOC_REGISTER;
+      resultreg    := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+      location.Register := resultreg;
+    end;
+    { determine operator }
+    if nodetype = shln then
+      op := OP_SHL
+    else
+      op := OP_SHR;
+    { shifting by a constant directly coded: }
+    if (right.nodetype = ordconstn) then
+    begin
+      if tordconstnode(right).Value.svalue and 31 <> 0 then
+        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, op, OS_32, tordconstnode(right).Value.svalue and 31, hregister1, resultreg);
+    end
+    else
+    begin
+      { load shift count in a register if necessary }
+      location_force_reg(current_asmdata.CurrAsmList, right.location, def_cgsize(right.resultdef), True);
+      cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, op, OS_32, right.location.Register, hregister1, resultreg);
+    end;
+  end;
+end;
+
+
+{*****************************************************************************
+                               TMIPSelNOTNODE
+*****************************************************************************}
+
+procedure tMIPSELnotnode.second_boolean;
+var
+  hl: tasmlabel;
+begin
+  { if the location is LOC_JUMP, we do the secondpass after the
+          labels are allocated
+        }
+  if left.expectloc = LOC_JUMP then
+  begin
+    hl := current_procinfo.CurrTrueLabel;
+    current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
+    current_procinfo.CurrFalseLabel := hl;
+    secondpass(left);
+    maketojumpbool(current_asmdata.CurrAsmList, left, lr_load_regvars);
+    hl := current_procinfo.CurrTrueLabel;
+    current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
+    current_procinfo.CurrFalseLabel := hl;
+    location.loc := LOC_JUMP;
+  end
+  else
+  begin
+    secondpass(left);
+    case left.location.loc of
+      LOC_FLAGS:
+      begin
+        internalerror(2007011501);
+      end;
+      LOC_REGISTER, LOC_CREGISTER, LOC_REFERENCE, LOC_CREFERENCE:
+      begin
+        location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
+        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SEQ, NR_TCR0, left.location.Register, NR_R0));
+        location_reset(location, LOC_REGISTER, OS_INT);
+        location.Register := NR_TCR0;
+      end;
+      else
+        internalerror(2003042401);
+    end;
+  end;
+end;
+
+
+begin
+  cmoddivnode := tMIPSELmoddivnode;
+  cshlshrnode := tMIPSELshlshrnode;
+  cnotnode    := tMIPSELnotnode;
+end.

+ 130 - 0
compiler/mips/ncpuset.pas

@@ -0,0 +1,130 @@
+{
+    Copyright (c) 1998-2004 by Florian Klaempfl and David Zhang
+
+    Generate MIPSEL assembler for in set/case nodes
+
+    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 ncpuset;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+  globtype,
+  nset,
+  ncgset;
+
+type
+  tcpucasenode = class(tcgcasenode)
+  protected
+    procedure optimizevalues(var max_linear_list: aint; var max_dist: aword); override;
+    function has_jumptable: boolean; override;
+    procedure genjumptable(hp: pcaselabel; min_, max_: aint); override;
+  end;
+
+
+implementation
+
+uses
+  globals,
+  systems,
+  constexp,
+  cpubase,
+  aasmbase, aasmtai, aasmcpu, aasmdata,
+  cgbase, cgutils, cgobj,
+  procinfo;
+
+procedure tcpucasenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
+begin
+  { give the jump table a higher priority }
+  max_dist := (max_dist * 3) div 2;
+end;
+
+
+function tcpucasenode.has_jumptable: boolean;
+begin
+  has_jumptable := True;
+end;
+
+
+procedure tcpucasenode.genjumptable(hp: pcaselabel; min_, max_: aint);
+var
+  table: tasmlabel;
+  last:  TConstExprInt;
+  indexreg, jmpreg, basereg: tregister;
+  href:  treference;
+  jumpsegment: TAsmlist;
+
+  procedure genitem(t: pcaselabel);
+  var
+    i: aint;
+  begin
+    if assigned(t^.less) then
+      genitem(t^.less);
+    { fill possible hole }
+    for i := last.svalue+1 to t^._low.svalue-1 do
+      jumpSegment.concat(Tai_const.Create_sym(elselabel));
+    for i := t^._low.svalue to t^._high.svalue do
+      jumpSegment.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+    last := t^._high;
+    if assigned(t^.greater) then
+      genitem(t^.greater);
+  end;
+
+begin
+  jumpsegment := current_procinfo.aktlocaldata;
+  if not (jumptable_no_range) then
+    begin
+      { case expr less than min_ => goto elselabel }
+      cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, aint(min_), hregister, elselabel);
+      { case expr greater than max_ => goto elselabel }
+      cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_gt, aint(max_), hregister, elselabel);
+    end;
+  current_asmdata.getjumplabel(table);
+  indexreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_ADDR, 2, hregister, indexreg);
+  { create reference }
+  reference_reset_symbol(href, table, 0, sizeof(aint));
+  href.offset := (-aint(min_)) * 4;
+  basereg     := cg.getaddressregister(current_asmdata.CurrAsmList);
+  cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList, href, basereg);
+
+  jmpreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+
+  reference_reset(href, sizeof(aint));
+  href.index := indexreg;
+  href.base  := basereg;
+  cg.a_load_ref_reg(current_asmdata.CurrAsmList, OS_ADDR, OS_ADDR, href, jmpreg);
+
+  current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JR, jmpreg));
+  { Delay slot }
+  current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+  { generate jump table }
+  if not(cs_opt_size in current_settings.optimizerswitches) then
+    jumpSegment.concat(Tai_Align.Create_Op(4, 0));
+  jumpSegment.concat(Tai_label.Create(table));
+  last := min_;
+  genitem(hp);
+end;
+
+
+
+begin
+  ccasenode := tcpucasenode;
+end.

+ 241 - 0
compiler/mips/strinst.inc

@@ -0,0 +1,241 @@
+'none',
+'p_stk2',
+'p_lw',
+'p_set_noreorder',
+'p_set_nomacro',
+'p_set_macro',
+'p_set_reorder',
+'p_frame',
+'p_mask',
+'p_fmask',
+'p_sw',
+'sparc8unimp',
+'nop',
+'not',
+'neg',
+'negu',
+'b',
+'li',
+'dli',
+'la',
+'move',
+'lb',
+'lbu',
+'lh',
+'lhu',
+'lw',
+'lwu',
+'lwl',
+'lwr',
+'ld',
+'ldl',
+'ldr',
+'ll',
+'lld',
+'sb',
+'sh',
+'sw',
+'swl',
+'swr',
+'sd',
+'sdl',
+'sdr',
+'sc',
+'scd',
+'sync',
+'addi',
+'daddi',
+'addiu',
+'daddiu',
+'slti',
+'sltiu',
+'andi',
+'ori',
+'xori',
+'lui',
+'dneg',
+'dnegu',
+'add',
+'dadd',
+'addu',
+'daddu',
+'sub',
+'dsub',
+'subu',
+'dsubu',
+'slt',
+'sltu',
+'and',
+'or',
+'xor',
+'nor',
+'mul',
+'mulo',
+'mulou',
+'dmul',
+'dmulo',
+'dmulou',
+'div',
+'divu',
+'ddiv',
+'ddivu',
+'rem',
+'remu',
+'drem',
+'dremu',
+'mult',
+'dmult',
+'multu',
+'dmultu',
+'mfhi',
+'mthi',
+'mflo',
+'mtlo',
+'multg',
+'dmultg',
+'multug',
+'dmultug',
+'divg',
+'ddivg',
+'divug',
+'ddivug',
+'modg',
+'dmodg',
+'modug',
+'dmodug',
+'j',
+'jal',
+'jr',
+'jalr',
+'beq',
+'bne',
+'blez',
+'bgtz',
+'bltz',
+'bgez',
+'bltzal',
+'bgezal',
+'beql',
+'bnel',
+'blezl',
+'bgtzl',
+'bltzl',
+'bgezl',
+'bltzall',
+'bgezall',
+'sll',
+'srl',
+'sra',
+'sllv',
+'srlv',
+'srav',
+'dsll',
+'dsrl',
+'dsra',
+'dsllv',
+'dsrlv',
+'dsrav',
+'dsll32',
+'dsrl32',
+'dsra32',
+'lwc1',
+'swc1',
+'ldc1',
+'sdc1',
+'mtc1',
+'mfc1',
+'dmtc1',
+'dmfc1',
+'ctc1',
+'cfc1',
+'add.s',
+'add.d',
+'sub.s',
+'sub.d',
+'mul.s',
+'mul.d',
+'div.s',
+'div.d',
+'abs.s',
+'abs.d',
+'neg.s',
+'neg.d',
+'sqrt.s',
+'sqrt.d',
+'mov.s',
+'mov.d',
+'cvt.s.d',
+'cvt.s.w',
+'cvt.s.l',
+'cvt.d.s',
+'cvt.d.w',
+'cvt.d.l',
+'cvt.w.s',
+'cvt.w.d',
+'cvt.l.s',
+'cvt.l.d',
+'round.w.s',
+'round.w.d',
+'round.l.s',
+'round.l.d',
+'trunc.w.s',
+'trunc.w.d',
+'trunc.l.s',
+'trunc.l.d',
+'ceil.w.s',
+'ceil.w.d',
+'ceil.l.s',
+'ceil.l.d',
+'floor.w.s',
+'floor.w.d',
+'floor.l.s',
+'floor.l.d',
+'bc1t',
+'bc1f',
+'bc1tl',
+'bc1fl',
+'c.eq.d',
+'c.eq.s',
+'c.le.d',
+'c.le.s',
+'c.lt.d',
+'c.lt.s',
+'beqi',
+'bnei',
+'blti',
+'blei',
+'bgti',
+'bgei',
+'bltui',
+'bleui',
+'bgtui',
+'bgeui',
+'blt',
+'ble',
+'bgt',
+'bge',
+'bltu',
+'bleu',
+'bgtu',
+'bgeu',
+'seq',
+'sge',
+'sgeu',
+'sgt',
+'sgtu',
+'sle',
+'sleu',
+'sne',
+'syscall',
+'add64sub',
+'sub64sub',
+'mul64sub',
+'div64sub',
+'neg64sub',
+'not64sub',
+'or64sub',
+'sar64sub',
+'shl64sub',
+'shr64sub',
+'xor64sub',
+'end_def'

+ 2 - 1
compiler/systems.pas

@@ -146,7 +146,8 @@ interface
              system_avr_embedded,       { 62 }
              system_i386_haiku,         { 63 }
              system_arm_darwin,         { 64 }
-             system_x86_64_solaris      { 65 }
+             system_x86_64_solaris,     { 65 }
+             system_mips_linux          { 66 }
        );
 
      type

+ 68 - 2
compiler/systems/i_linux.pas

@@ -728,7 +728,69 @@ unit i_linux;
           );
 {$endif FPC_ARMEB}
 {$endif FPC_ARMEL}
-
+{
+       system_fvm32_linux_info : tsysteminfo =
+          (
+            system       : system_mips_LINUX;
+            name         : 'Linux for MIPS';
+            shortname    : 'Linux';
+            flags        : [tf_needs_symbol_size];
+            cpu          : cpu_mips;
+            unit_env     : 'LINUXUNITS';
+            extradefines : 'UNIX;HASUNIX';
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.s';
+            objext       : '.o';
+            resext       : '.res';
+            resobjext    : '.or';
+            sharedlibext : '.so';
+            staticlibext : '.a';
+            staticlibprefix : 'libp';
+            sharedlibprefix : 'lib';
+            sharedClibext : '.so';
+            staticClibext : '.a';
+            staticClibprefix : 'lib';
+            sharedClibprefix : 'lib';
+//            p_ext_support : false;
+            Cprefix      : '';
+            newline      : #10;
+            dirsep       : '/';
+            files_case_relevent : true;
+            assem        : as_gas;
+            assemextern  : as_gas;
+            link         : nil;
+            linkextern   : nil;
+            ar           : ar_gnu_ar;
+            res          : res_none;
+            script       : script_unix;
+            endian       : endian_little;
+            alignment    :
+              (
+                procalign       : 4;
+                loopalign       : 4;
+                jumpalign       : 0;
+                constalignmin   : 0;
+                constalignmax   : 8;
+                varalignmin     : 0;
+                varalignmax     : 8;
+                localalignmin   : 4;
+                localalignmax   : 8;
+                recordalignmin  : 0;
+                recordalignmax  : 2;
+                maxCrecordalign : 4
+              );
+            first_parm_offset : 8;
+            stacksize    : 32*1024*1024;
+            DllScanSupported:false;
+            use_function_relative_addresses : true;
+            abi : abi_default
+          );
+}
   implementation
 
 initialization
@@ -775,5 +837,9 @@ initialization
     set_source_info(system_arm_linux_info);
   {$endif linux}
 {$endif CPUARM}
+{$ifdef CPUMIPSEL}
+  {$ifdef linux}
+    set_source_info(system_mipsel_linux_info);
+  {$endif linux}
+{$endif CPUMIPSEL}
 end.
-

+ 7 - 0
compiler/systems/t_linux.pas

@@ -137,6 +137,7 @@ const
 {$ifdef sparc}  platform_select='-b elf32-sparc -m elf32_sparc';{$endif}
 {$ifdef arm}    platform_select='';{$endif} {unknown :( }
 {$ifdef m68k}    platform_select='';{$endif} {unknown :( }
+{$ifdef mips}    platform_select='';{$endif} {unknown :( }
 
 var
   defdynlinker: string;
@@ -1163,5 +1164,11 @@ initialization
   RegisterExport(system_arm_linux,texportliblinux);
   RegisterTarget(system_arm_linux_info);
 {$endif ARM}
+{$ifdef MIPS}
+  RegisterExternalLinker(system_mipsel_linux_info,TLinkerLinux);
+  RegisterImport(system_mipsel_linux,timportliblinux);
+  RegisterExport(system_mipsel_linux,texportliblinux);
+  RegisterTarget(system_mipsel_linux_info);
+{$endif MIPS}
   RegisterRes(res_elf_info,TWinLikeResourceFile);
 end.