瀏覽代碼

* continued to play with avr

git-svn-id: trunk@11584 -
florian 17 年之前
父節點
當前提交
43f3b72139
共有 3 個文件被更改,包括 266 次插入0 次删除
  1. 1 0
      .gitattributes
  2. 1 0
      compiler/avr/cpunode.pas
  3. 264 0
      compiler/avr/navrmat.pas

+ 1 - 0
.gitattributes

@@ -90,6 +90,7 @@ compiler/avr/cpupi.pas svneol=native#text/plain
 compiler/avr/cputarg.pas svneol=native#text/plain
 compiler/avr/cputarg.pas svneol=native#text/plain
 compiler/avr/itcpugas.pas svneol=native#text/plain
 compiler/avr/itcpugas.pas svneol=native#text/plain
 compiler/avr/navradd.pas svneol=native#text/plain
 compiler/avr/navradd.pas svneol=native#text/plain
+compiler/avr/navrmat.pas svneol=native#text/plain
 compiler/avr/raavr.pas svneol=native#text/plain
 compiler/avr/raavr.pas svneol=native#text/plain
 compiler/avr/raavrgas.pas svneol=native#text/plain
 compiler/avr/raavrgas.pas svneol=native#text/plain
 compiler/avr/ravrcon.inc svneol=native#text/plain
 compiler/avr/ravrcon.inc svneol=native#text/plain

+ 1 - 0
compiler/avr/cpunode.pas

@@ -35,6 +35,7 @@ unit cpunode;
          after the generic one (FK)
          after the generic one (FK)
        }
        }
        ,navradd
        ,navradd
+       ,navrmat
        ;
        ;
 
 
 
 

+ 264 - 0
compiler/avr/navrmat.pas

@@ -0,0 +1,264 @@
+{
+    Copyright (c) 1998-2008 by Florian Klaempfl
+
+    Generates AVR 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 navrmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,nmat,ncgmat;
+
+    type
+      tavrmoddivnode = class(tmoddivnode)
+        function first_moddivint: tnode;override;
+        procedure pass_generate_code;override;
+      end;
+
+      tavrnotnode = class(tcgnotnode)
+        procedure second_boolean;override;
+      end;
+
+implementation
+
+    uses
+      globtype,systems,
+      cutils,verbose,globals,constexp,
+      aasmbase,aasmcpu,aasmtai,aasmdata,
+      defutil,
+      cgbase,cgobj,cgutils,
+      pass_2,procinfo,
+      ncon,
+      cpubase,
+      ncgutil,cgcpu;
+
+{*****************************************************************************
+                             TAVRMODDIVNODE
+*****************************************************************************}
+
+    function tavrmoddivnode.first_moddivint: tnode;
+      var
+        power  : longint;
+      begin
+        if (right.nodetype=ordconstn) and
+          (nodetype=divn) and
+          (ispowerof2(tordconstnode(right).value,power) or
+           (tordconstnode(right).value=1) or
+           (tordconstnode(right).value=int64(-1))
+          ) and
+          not(is_64bitint(resultdef)) then
+          result:=nil
+        else
+          result:=inherited first_moddivint;
+      end;
+
+
+    procedure tavrmoddivnode.pass_generate_code;
+      var
+        power  : longint;
+        numerator,
+        helper1,
+        helper2,
+        resultreg  : tregister;
+        size       : Tcgsize;
+        so : tshifterop;
+{
+       procedure genOrdConstNodeDiv;
+         begin
+           if tordconstnode(right).value=0 then
+             internalerror(2005061701)
+           else if tordconstnode(right).value=1 then
+             cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, numerator, resultreg)
+           else if (tordconstnode(right).value = int64(-1)) then
+             begin
+               // note: only in the signed case possible..., may overflow
+               current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MVN,
+                 resultreg,numerator),toppostfix(ord(cs_check_overflow in current_settings.localswitches)*ord(PF_S))));
+             end
+           else if ispowerof2(tordconstnode(right).value,power) then
+             begin
+               if (is_signed(right.resultdef)) then
+                 begin
+                    helper1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                    helper2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                    shifterop_reset(so);
+                    so.shiftmode:=SM_ASR;
+                    so.shiftimm:=31;
+                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_shifterop(A_MOV,helper1,numerator,so));
+                    shifterop_reset(so);
+                    so.shiftmode:=SM_LSR;
+                    so.shiftimm:=32-power;
+                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,helper2,numerator,helper1,so));
+                    shifterop_reset(so);
+                    so.shiftmode:=SM_ASR;
+                    so.shiftimm:=power;
+                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_shifterop(A_MOV,resultreg,helper2,so));
+                  end
+               else
+                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,numerator,resultreg)
+             end;
+         end;
+}
+{
+       procedure genOrdConstNodeMod;
+         var
+             modreg, maskreg, tempreg : tregister;
+         begin
+             if (tordconstnode(right).value = 0) then begin
+                 internalerror(2005061702);
+             end
+             else if (abs(tordconstnode(right).value.svalue) = 1) then
+             begin
+                // x mod +/-1 is always zero
+                cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, resultreg);
+             end
+             else if (ispowerof2(tordconstnode(right).value, power)) then
+             begin
+                 if (is_signed(right.resultdef)) then begin
+
+                     tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+                     maskreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+                     modreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+                     cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, abs(tordconstnode(right).value.svalue)-1, modreg);
+                     cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, maskreg);
+                     cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+                     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+                     cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, modreg, maskreg, maskreg);
+                     cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+                 end else begin
+                     cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).value.svalue-1, numerator, resultreg);
+                 end;
+             end else begin
+                 genOrdConstNodeDiv();
+                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, tordconstnode(right).value.svalue, resultreg, resultreg);
+                 cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+             end;
+         end;
+}
+
+      begin
+{
+        secondpass(left);
+        secondpass(right);
+        location_copy(location,left.location);
+
+        { put numerator in register }
+        size:=def_cgsize(left.resultdef);
+        location_force_reg(current_asmdata.CurrAsmList,left.location,
+          size,true);
+        location_copy(location,left.location);
+        numerator:=location.register;
+        resultreg:=location.register;
+        if location.loc=LOC_CREGISTER then
+          begin
+            location.loc := LOC_REGISTER;
+            location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+            resultreg:=location.register;
+          end
+        else if (nodetype=modn) or (right.nodetype=ordconstn) then
+          begin
+            // for a modulus op, and for const nodes we need the result register
+            // to be an extra register
+            resultreg:=cg.getintregister(current_asmdata.CurrAsmList,size);
+          end;
+
+        if right.nodetype=ordconstn then
+          begin
+            if nodetype=divn then
+              genOrdConstNodeDiv
+            else
+//              genOrdConstNodeMod;
+          end;
+
+        location.register:=resultreg;
+
+        { unsigned division/module can only overflow in case of division by zero }
+        { (but checking this overflow flag is more convoluted than performing a  }
+        {  simple comparison with 0)                                             }
+        if is_signed(right.resultdef) then
+          cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+}
+      end;
+
+{*****************************************************************************
+                               TAVRNOTNODE
+*****************************************************************************}
+
+    procedure tavrnotnode.second_boolean;
+      var
+        hl : tasmlabel;
+        tmpreg : tregister;
+        i : longint;
+      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
+                  location_copy(location,left.location);
+                  inverse_flags(location.resflags);
+                end;
+              LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE,
+              LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF :
+                begin
+                  location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+                  current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0));
+                  tmpreg:=left.location.register;
+
+                  { avr has no cpci, so we use the first register as "zero" register }
+                  for i:=2 to tcgsize2size[left.location.size] do
+                    begin
+                      current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg,left.location.register));
+                    end;
+                  location_reset(location,LOC_FLAGS,OS_NO);
+                  location.resflags:=F_EQ;
+               end;
+              else
+                internalerror(2003042401);
+            end;
+          end;
+      end;
+
+begin
+  cmoddivnode:=tavrmoddivnode;
+  cnotnode:=tavrnotnode;
+end.