Bläddra i källkod

+ Z80: implemented TCpuAsmOptimizer.InstructionLoadsFromReg

git-svn-id: trunk@45344 -
nickysn 5 år sedan
förälder
incheckning
bb4d7a7a50
1 ändrade filer med 100 tillägg och 36 borttagningar
  1. 100 36
      compiler/z80/aoptcpu.pas

+ 100 - 36
compiler/z80/aoptcpu.pas

@@ -176,44 +176,108 @@ Implementation
   function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
     var
       p: taicpu;
-      i: longint;
     begin
       Result := false;
-
-      internalerror(2017032607);
-
-      //if not (assigned(hp) and (hp.typ = ait_instruction)) then
-      //  exit;
-      //p:=taicpu(hp);
-      //
-      //i:=0;
-      //
-      //{ we do not care about the stack pointer }
-      //if p.opcode in [A_POP] then
-      //  exit;
-      //
-      //{ first operand only written?
-      //  then skip it }
-      //if p.opcode in [A_MOV,A_LD,A_LDD,A_LDS,A_LPM,A_LDI,A_MOVW] then
-      //  i:=1;
-      //
-      //while(i<p.ops) do
-      //  begin
-      //    case p.oper[I]^.typ of
-      //      top_reg:
-      //        Result := (p.oper[I]^.reg = reg) or
-      //          { MOVW }
-      //          ((i=1) and (p.opcode=A_MOVW) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg)));
-      //      top_ref:
-      //        Result :=
-      //          (p.oper[I]^.ref^.base = reg) or
-      //          (p.oper[I]^.ref^.index = reg);
-      //    end;
-      //    { Bailout if we found something }
-      //    if Result then
-      //      exit;
-      //    Inc(I);
-      //  end;
+      if not (assigned(hp) and (hp.typ = ait_instruction)) then
+        exit;
+      p:=taicpu(hp);
+
+      case p.opcode of
+        A_LD,A_BIT,A_SET,A_RES:
+          begin
+            if p.ops<>2 then
+              internalerror(2020051102);
+            result:=((p.oper[0]^.typ=top_ref) and RegInRef(reg,p.oper[0]^.ref^)) or
+                    RegInOp(reg,p.oper[1]^);
+          end;
+        A_PUSH,A_INC,A_DEC,A_RLC,A_RRC,A_SLA,A_SRA,A_SRL:
+          begin
+            if p.ops<>1 then
+              internalerror(2020051103);
+            result:=RegInOp(reg,p.oper[0]^);
+          end;
+        A_POP:
+          result:=(reg=NR_SP);
+        A_EX,A_ADD,A_SUB,A_AND,A_OR,A_XOR,A_CP:
+          begin
+            if p.ops<>2 then
+              internalerror(2020051104);
+            result:=RegInOp(reg,p.oper[0]^) or
+                    RegInOp(reg,p.oper[1]^);
+          end;
+        A_EXX:
+          result:=SuperRegistersEqual(reg,NR_BC)  or SuperRegistersEqual(reg,NR_DE)  or SuperRegistersEqual(reg,NR_HL) or
+                  SuperRegistersEqual(reg,NR_BC_) or SuperRegistersEqual(reg,NR_DE_) or SuperRegistersEqual(reg,NR_HL_);
+        A_LDI,A_LDIR,A_LDD,A_LDDR:
+          result:=SuperRegistersEqual(reg,NR_BC) or SuperRegistersEqual(reg,NR_DE) or SuperRegistersEqual(reg,NR_HL);
+        A_CPI,A_CPIR,A_CPD,A_CPDR:
+          result:=SuperRegistersEqual(reg,NR_BC) or SuperRegistersEqual(reg,NR_HL) or RegistersInterfere(reg,NR_A);
+        A_ADC,A_SBC:
+          begin
+            if p.ops<>2 then
+              internalerror(2020051105);
+            result:=RegInOp(reg,p.oper[0]^) or
+                    RegInOp(reg,p.oper[1]^) or (reg=NR_CARRYFLAG) or (reg=NR_DEFAULTFLAGS);
+          end;
+        A_DAA:
+          result:=RegistersInterfere(reg,NR_A) or (reg=NR_CARRYFLAG) or (reg=NR_HALFCARRYFLAG) or (reg=NR_ADDSUBTRACTFLAG) or (reg=NR_DEFAULTFLAGS);
+        A_CPL,A_NEG,A_RLCA,A_RRCA:
+          result:=RegistersInterfere(reg,NR_A);
+        A_CCF:
+          result:=(reg=NR_CARRYFLAG) or (reg=NR_DEFAULTFLAGS);
+        A_SCF,A_NOP,A_HALT,A_DI,A_EI,A_IM:
+          result:=false;
+        A_RLA,A_RRA:
+          result:=RegistersInterfere(reg,NR_A) or (reg=NR_CARRYFLAG) or (reg=NR_DEFAULTFLAGS);
+        A_RL,A_RR:
+          begin
+            if p.ops<>1 then
+              internalerror(2020051106);
+            result:=RegInOp(reg,p.oper[0]^) or (reg=NR_CARRYFLAG) or (reg=NR_DEFAULTFLAGS);
+          end;
+        A_RLD,A_RRD:
+          result:=RegistersInterfere(reg,NR_A) or RegistersInterfere(reg,NR_HL);
+        A_JP,A_JR:
+          begin
+            if p.ops<>1 then
+              internalerror(2020051107);
+            if RegInOp(reg,p.oper[0]^) then
+              result:=true
+            else
+              case p.condition of
+                C_None:
+                  result:=false;
+                C_NZ,C_Z:
+                  result:=(reg=NR_ZEROFLAG) or (reg=NR_DEFAULTFLAGS);
+                C_NC,C_C:
+                  result:=(reg=NR_CARRYFLAG) or (reg=NR_DEFAULTFLAGS);
+                C_PO,C_PE:
+                  result:=(reg=NR_PARITYOVERFLOWFLAG) or (reg=NR_DEFAULTFLAGS);
+                C_P,C_M:
+                  result:=(reg=NR_SIGNFLAG) or (reg=NR_DEFAULTFLAGS);
+              end;
+          end;
+        A_DJNZ:
+          result:=RegistersInterfere(reg,NR_B);
+        A_CALL,A_RET,A_RETI,A_RETN,A_RST:
+          result:=true;
+        A_IN:
+          begin
+            if p.ops<>2 then
+              internalerror(2020051109);
+            result:=(p.oper[1]^.typ=top_ref) and (p.oper[1]^.ref^.base=NR_C) and RegistersInterfere(reg,NR_BC);
+          end;
+        A_OUT:
+          begin
+            if p.ops<>2 then
+              internalerror(2020051110);
+            result:=RegInOp(reg,p.oper[1]^) or (p.oper[0]^.typ=top_ref) and (p.oper[0]^.ref^.base=NR_C) and RegistersInterfere(reg,NR_BC);
+          end;
+        A_INI,A_INIR,A_IND,A_INDR,A_OUTI,A_OTIR,A_OUTD,A_OTDR:
+          result:=SuperRegistersEqual(reg,NR_BC) or SuperRegistersEqual(reg,NR_HL);
+        else
+          internalerror(2020051101);
+      end;
     end;
 
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;