Procházet zdrojové kódy

* today's arm patches

florian před 22 roky
rodič
revize
dc7d8ba847

+ 20 - 66
compiler/arm/aasmcpu.pas

@@ -155,6 +155,7 @@ implementation
          loadreg(1,_op2);
       end;
 
+
     constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
       begin
          inherited create(op);
@@ -201,6 +202,7 @@ implementation
          loadreg(2,_op3);
       end;
 
+
      constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: Longint);
        begin
          inherited create(op);
@@ -214,6 +216,7 @@ implementation
          loadconst(2,aword(_op3));
       end;
 
+
      constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
        begin
          inherited create(op);
@@ -318,6 +321,7 @@ implementation
          loadconst(4,cardinal(_op5));
       end;
 
+
      constructor taicpu.op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : Longint);
       begin
          inherited create(op);
@@ -333,6 +337,7 @@ implementation
          loadconst(4,cardinal(_op5));
       end;
 
+
     constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
       begin
          inherited create(op);
@@ -341,6 +346,7 @@ implementation
          loadsymbol(0,_op1,0);
       end;
 
+
      constructor taicpu.op_const_const_sym(op : tasmop;_op1,_op2 : longint; _op3: tasmsymbol);
       begin
          inherited create(op);
@@ -406,7 +412,8 @@ implementation
                              r:Tsupregset;
                              var unusedregsint:Tsupregset;
                               const spilltemplist:Tspill_temp_list): boolean;
-{$ifdef dummy}
+
+
       function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
 
       var back:Tsupregset;
@@ -466,63 +473,11 @@ implementation
           result := true;
           wasload := true;
           case op of
-            A_LBZ:
+            A_LDR:
               begin
-                counterpart := A_STB;
+                counterpart := A_STR;
               end;
-            A_LBZX:
-              begin
-                counterpart := A_STBX;
-              end;
-            A_LHZ,A_LHA:
-              begin
-                counterpart := A_STH;
-              end;
-            A_LHZX,A_LHAX:
-              begin
-                counterpart := A_STHX;
-              end;
-            A_LWZ:
-              begin
-                counterpart := A_STW;
-              end;
-            A_LWZX:
-              begin
-                counterpart := A_STWX;
-              end;
-            A_STB:
-              begin
-                counterpart := A_LBZ;
-                wasload := false;
-              end;
-            A_STBX:
-              begin
-                counterpart := A_LBZX;
-                wasload := false;
-              end;
-            A_STH:
-              begin
-                counterpart := A_LHZ;
-                wasload := false;
-              end;
-            A_STHX:
-              begin
-                counterpart := A_LHZX;
-                wasload := false;
-              end;
-            A_STW:
-              begin
-                counterpart := A_LWZ;
-                wasload := false;
-              end;
-            A_STWX:
-              begin
-                counterpart := A_LWZX;
-                wasload := false;
-              end;
-            A_LBZU,A_LBZUX,A_LHZU,A_LHZUX,A_LHAU,A_LHAUX,
-            A_LWZU,A_LWZUX,A_STBU,A_STBUX,A_STHU,A_STHUX,
-            A_STWU,A_STWUX:
+            A_LDM:
               internalerror(2003070602);
             else
               result := false;
@@ -602,7 +557,7 @@ implementation
                   pos:=get_insert_pos(Tai(previous),oper[1].ref^.index.number shr 8,0,0);
                 rgget(list,pos,0,helpreg);
                 spill_registers:=true;
-                helpins:=Taicpu.op_reg_ref(A_LWZ,helpreg,spilltemplist[supreg]);
+                helpins:=Taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
                 if pos=nil then
                   list.insertafter(helpins,list.first)
                 else
@@ -626,7 +581,7 @@ implementation
                   pos:=get_insert_pos(Tai(previous),oper[1].ref^.base.number shr 8,0,0);
                 rgget(list,pos,0,helpreg);
                 spill_registers:=true;
-                helpins:=Taicpu.op_reg_ref(A_LWZ,helpreg,spilltemplist[supreg]);
+                helpins:=Taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
                 if pos=nil then
                   list.insertafter(helpins,list.first)
                 else
@@ -675,9 +630,9 @@ implementation
             pos := get_insert_pos(Tai(previous),reg1,reg2,reg3);
             rgget(list,pos,0,helpreg);
             spill_registers := true;
-            helpins := taicpu.op_reg_ref(A_STW,helpreg,spilltemplist[supreg]);
+            helpins := taicpu.op_reg_ref(A_STR,helpreg,spilltemplist[supreg]);
             list.insertafter(helpins,self);
-            helpins := taicpu.op_reg_ref(A_LWZ,helpreg,spilltemplist[supreg]);
+            helpins := taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
             if pos=nil then
               list.insertafter(helpins,list.first)
             else
@@ -709,7 +664,7 @@ implementation
                   pos := get_insert_pos(Tai(previous),reg1,reg2,reg3);
                   rgget(list,pos,0,helpreg);
                   spill_registers := true;
-                  helpins := taicpu.op_reg_ref(A_LWZ,helpreg,spilltemplist[supreg]);
+                  helpins := taicpu.op_reg_ref(A_LDR,helpreg,spilltemplist[supreg]);
                   if pos=nil then
                     list.insertafter(helpins,list.first)
                   else
@@ -724,10 +679,6 @@ implementation
                 end;
             end;
       end;
-{$else dummy}
-      begin
-      end;
-{$endif dummy}
 
 
     procedure InitAsm;
@@ -742,7 +693,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.5  2003-08-27 00:27:56  florian
+  Revision 1.6  2003-08-28 00:05:29  florian
+    * today's arm patches
+
+  Revision 1.5  2003/08/27 00:27:56  florian
     + same procedure as very day: today's work on arm
 
   Revision 1.4  2003/08/25 23:20:38  florian

+ 31 - 9
compiler/arm/agarmgas.pas

@@ -100,10 +100,6 @@ unit agarmgas;
                s:=s+tostr(offset);
             end;
 
-           if (index.enum < firstreg) or (index.enum > lastreg) then
-             internalerror(20030312);
-           if (base.enum < firstreg) or (base.enum > lastreg) then
-             internalerror(200303123);
            if (index.enum=R_NO) and (base.enum<>R_NO) then
              begin
                 if offset=0 then
@@ -113,7 +109,10 @@ unit agarmgas;
                      else
                        s:=s+'0';
                   end;
-                s:=s+'['+std_reg2str[base.enum]+']'
+                if base.enum=R_INTREGISTER then
+                  s:=s+'('+gas_regname(base.number)+')'
+                else
+                  s:=s+'('+gas_reg2str[base.enum]+')';
              end
            else if (index.enum<>R_NO) and (base.enum<>R_NO) and (offset=0) then
              s:=s+std_reg2str[base.enum]+','+std_reg2str[index.enum]
@@ -175,12 +174,23 @@ unit agarmgas;
       case o.typ of
         top_reg:
           begin
-            if (o.reg.enum < R_R0) or (o.reg.enum > lastreg) then
-              internalerror(200303125);
-            getopstr:=std_reg2str[o.reg.enum];
+            if o.reg.enum=R_INTREGISTER then
+              getopstr:=gas_regname(o.reg.number)
+            else
+              getopstr:=gas_reg2str[o.reg.enum];
           end;
         top_shifterop:
           begin
+            if (o.shifterop^.rs.enum<>R_NO) and (o.shifterop^.shiftimm=0) then
+              begin
+                if o.shifterop^.rs.enum=R_INTREGISTER then
+                  getopstr:=shifterop2str[o.shifterop^.shiftertype]+' '+gas_regname(o.shifterop^.rs.number)
+                else
+                  getopstr:=shifterop2str[o.shifterop^.shiftertype]+' '+gas_reg2str[o.shifterop^.rs.enum];
+              end
+            else if (o.shifterop^.rs.enum=R_NO) then
+              getopstr:=shifterop2str[o.shifterop^.shiftertype]+' #'+tostr(o.shifterop^.shiftimm)
+            else internalerror(200308282);
           end;
         top_const:
           getopstr:=tostr(longint(o.val));
@@ -263,7 +273,16 @@ unit agarmgas;
 
 
   function gas_regname(const r:Tnewregister):string;
+    var s:Tsuperregister;
     begin
+      s:=r shr 8;
+      if s in [RS_R0..RS_R15] then
+        gas_regname:='r'+tostr(s-RS_R0)
+      else
+        begin
+          {Generate a systematic name.}
+          gas_regname:='reg'+tostr(s)+'d';
+        end;
     end;
 
 
@@ -273,7 +292,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.3  2003-08-24 12:27:26  florian
+  Revision 1.4  2003-08-28 00:05:29  florian
+    * today's arm patches
+
+  Revision 1.3  2003/08/24 12:27:26  florian
     * continued to work on the arm port
 
   Revision 1.2  2003/08/20 15:50:12  florian

+ 104 - 3
compiler/arm/cgcpu.pas

@@ -272,6 +272,7 @@ unit cgcpu;
 
      procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
        begin
+         a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
        end;
 
 
@@ -283,7 +284,44 @@ unit cgcpu;
 
      procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
        size: tcgsize; src1, src2, dst: tregister);
-       begin
+       const
+         op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
+           (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
+            A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
+       var
+         so : tshifterop;
+       begin
+         case op of
+           OP_NEG:
+             list.concat(taicpu.op_reg_reg(op_reg_reg_opcg2asmop[op],dst,dst));
+           OP_NOT:
+             list.concat(taicpu.op_reg_reg(A_MVN,dst,dst));
+           OP_DIV,OP_IDIV:
+             internalerror(200308281);
+           OP_SHL:
+             begin
+               shifterop_reset(so);
+               so.rs:=src2;
+               so.shiftertype:=SO_LSL;
+               list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src1,so));
+             end;
+           OP_SHR:
+             begin
+               shifterop_reset(so);
+               so.rs:=src2;
+               so.shiftertype:=SO_LSR;
+               list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src1,so));
+             end;
+           OP_SAR:
+             begin
+               shifterop_reset(so);
+               so.rs:=src2;
+               so.shiftertype:=SO_LSL;
+               list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src1,so));
+             end;
+           else
+             list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
+         end;
        end;
 
 
@@ -345,7 +383,61 @@ unit cgcpu;
 
 
      procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
-       begin
+       var
+         instr: taicpu;
+         so : tshifterop;
+       begin
+         shifterop_reset(so);
+         if (reg1.enum<>R_INTREGISTER) or (reg1.number = 0) then
+           internalerror(200303101);
+         if (reg2.enum<>R_INTREGISTER) or (reg2.number = 0) then
+           internalerror(200303102);
+         if (reg1.number<>reg2.number) or
+            (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
+            ((tcgsize2size[tosize] = tcgsize2size[fromsize]) and
+             (tosize <> fromsize) and
+             not(fromsize in [OS_32,OS_S32])) then
+           begin
+             case tosize of
+               OS_8:
+                 instr := taicpu.op_reg_reg_const(A_AND,
+                   reg2,reg1,$ff);
+               OS_S8:
+                 begin
+                   so.shiftertype:=SO_LSL;
+                   so.shiftimm:=24;
+                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
+                   so.shiftertype:=SO_ASR;
+                   so.shiftimm:=24;
+                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
+                 end;
+               OS_16:
+                 begin
+                   so.shiftertype:=SO_LSL;
+                   so.shiftimm:=16;
+                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
+                   so.shiftertype:=SO_LSR;
+                   so.shiftimm:=16;
+                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
+                 end;
+               OS_S16:
+                 begin
+                   so.shiftertype:=SO_LSL;
+                   so.shiftimm:=16;
+                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
+                   so.shiftertype:=SO_ASR;
+                   so.shiftimm:=16;
+                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
+                 end;
+               OS_32,OS_S32:
+                 begin
+                   instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+                   rg.add_move_instruction(instr);
+                   list.concat(instr);
+                 end;
+               else internalerror(2002090901);
+             end;
+           end;
        end;
 
 
@@ -383,7 +475,13 @@ unit cgcpu;
 
 
      procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
+       var
+         ai : taicpu;
        begin
+         ai := Taicpu.op_sym(A_B,l);
+         ai.SetCondition(flags_to_cond(f));
+         ai.is_jmp := true;
+         list.concat(ai);
        end;
 
 
@@ -493,7 +591,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.5  2003-08-25 23:20:38  florian
+  Revision 1.6  2003-08-28 00:05:29  florian
+    * today's arm patches
+
+  Revision 1.5  2003/08/25 23:20:38  florian
     + started to implement FPU support for the ARM
     * fixed a lot of other things
 

+ 35 - 2
compiler/arm/cpubase.pas

@@ -612,10 +612,17 @@ uses
 
     procedure shifterop_reset(var so : tshifterop);
 
-implementation
+  implementation
+
+    uses
+      verbose;
 
     procedure convert_register_to_enum(var r:Tregister);
       begin
+        if r.enum = R_INTREGISTER then
+          r.enum := toldregister(r.number shr 8)
+        else
+          internalerror(200308271);
       end;
 
 
@@ -643,14 +650,37 @@ implementation
 
 
     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 supreg_name(r:Tsuperregister):string;
+      const
+        supreg_names:array[0..last_supreg] of string[3]=
+          ('inv',
+           'r0' ,'r2', 'r3','r4','r5','r6','r7','r8',
+           'r8' ,'r9', 'r10','r11','r12','r13','r14','pc'
+           );
+      var
+        s : string[4];
       begin
+        if r in [0..last_supreg] then
+          supreg_name:=supreg_names[r]
+        else
+          begin
+            str(r,s);
+            supreg_name:='reg'+s;
+          end;
       end;
 
+
     procedure shifterop_reset(var so : tshifterop);
       begin
         FillChar(so,sizeof(so),0);
@@ -660,7 +690,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.7  2003-08-25 23:20:38  florian
+  Revision 1.8  2003-08-28 00:05:29  florian
+    * today's arm patches
+
+  Revision 1.7  2003/08/25 23:20:38  florian
     + started to implement FPU support for the ARM
     * fixed a lot of other things
 

+ 5 - 2
compiler/arm/cpunode.pas

@@ -38,14 +38,17 @@ unit cpunode;
        narmadd,
        narmcal,
        narmmat,
-//!!!       narminl,
+       narminl,
        narmcnv
        ;
 
 end.
 {
   $Log$
-  Revision 1.6  2003-08-27 00:27:56  florian
+  Revision 1.7  2003-08-28 00:05:29  florian
+    * today's arm patches
+
+  Revision 1.6  2003/08/27 00:27:56  florian
     + same procedure as very day: today's work on arm
 
   Revision 1.5  2003/08/25 23:20:38  florian

+ 128 - 0
compiler/arm/narminl.pas

@@ -0,0 +1,128 @@
+{
+    $Id$
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generates ARM 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 narminl;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,ninl,ncginl;
+
+    type
+      tarminlinenode = 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
+      globtype,systems,
+      cutils,verbose,globals,fmodule,
+      symconst,symdef,
+      aasmbase,aasmtai,aasmcpu,
+      cginfo,cgbase,pass_1,pass_2,
+      cpubase,paramgr,
+      nbas,ncon,ncal,ncnv,nld,
+      tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
+
+{*****************************************************************************
+                              tarminlinenode
+*****************************************************************************}
+
+    procedure tarminlinenode.load_fpu_location;
+      begin
+        secondpass(left);
+        location_force_fpureg(exprasmlist,left.location,true);
+        location_copy(location,left.location);
+        if left.location.loc=LOC_CFPUREGISTER then
+          begin
+           location.register:=rg.getregisterfpu(exprasmlist,location.size);
+           location.loc := LOC_FPUREGISTER;
+         end;
+      end;
+
+
+    function tarminlinenode.first_abs_real : tnode;
+      begin
+        expectloc:=LOC_FPUREGISTER;
+        registers32:=left.registers32;
+        registersfpu:=max(left.registersfpu,1);
+        first_abs_real := nil;
+      end;
+
+
+    function tarminlinenode.first_sqr_real : tnode;
+      begin
+        expectloc:=LOC_FPUREGISTER;
+        registers32:=left.registers32;
+        registersfpu:=max(left.registersfpu,1);
+        first_sqr_real:=nil;
+      end;
+
+
+    function tarminlinenode.first_sqrt_real : tnode;
+      begin
+        expectloc:=LOC_FPUREGISTER;
+        registers32:=left.registers32;
+        registersfpu:=max(left.registersfpu,1);
+        first_sqrt_real := nil;
+      end;
+
+
+    procedure tarminlinenode.second_abs_real;
+      begin
+        load_fpu_location;
+        exprasmlist.concat(taicpu.op_reg(A_ABS,location.register));
+      end;
+
+
+    procedure tarminlinenode.second_sqr_real;
+      begin
+        load_fpu_location;
+        exprasmlist.concat(taicpu.op_reg_reg(A_MUF,location.register,left.location.register));
+      end;
+
+
+    procedure tarminlinenode.second_sqrt_real;
+      begin
+        load_fpu_location;
+        exprasmlist.concat(taicpu.op_reg(A_SQT,location.register));
+      end;
+
+begin
+  cinlinenode:=tarminlinenode;
+end.
+{
+  $Log$
+  Revision 1.1  2003-08-28 00:05:29  florian
+    * today's arm patches
+}