Browse Source

+ more compilations fixes and units added

Nikolay Nikolov 1 year ago
parent
commit
cbba9fa893

+ 460 - 0
compiler/mos6502/aoptcpu.pas

@@ -0,0 +1,460 @@
+{
+    Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+    Development Team
+
+    This unit implements the MOS Technology 6502 optimizer object
+
+    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 aoptcpu;
+
+{$i fpcdefs.inc}
+
+{$define DEBUG_AOPTCPU}
+
+Interface
+
+uses cpubase, cgbase, aasmtai, aopt,AoptObj, aoptcpub;
+
+Type
+  TCpuAsmOptimizer = class(TAsmOptimizer)
+    { outputs a debug message into the assembler file }
+    procedure DebugMsg(const s: string; p: tai);
+
+    Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
+    function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
+    function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; override;
+
+    { uses the same constructor as TAopObj }
+    function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+    procedure PeepHoleOptPass2;override;
+  End;
+
+Implementation
+
+  uses
+    cutils,
+    verbose,
+    cpuinfo,
+    aasmbase,aasmcpu,aasmdata,
+    globals,globtype,
+    cgutils;
+
+  type
+    TAsmOpSet = set of TAsmOp;
+
+  function CanBeCond(p : tai) : boolean;
+    begin
+      result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
+    end;
+
+
+  function RefsEqual(const r1, r2: treference): boolean;
+    begin
+      refsequal :=
+        (r1.offset = r2.offset) and
+        (r1.base = r2.base) and
+        (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and
+        (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and
+        (r1.relsymbol = r2.relsymbol);
+    end;
+
+
+  function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline;
+    begin
+      result:=oper1.typ=oper2.typ;
+
+      if result then
+        case oper1.typ of
+          top_const:
+            Result:=oper1.val = oper2.val;
+          top_reg:
+            Result:=oper1.reg = oper2.reg;
+          top_ref:
+            Result:=RefsEqual(oper1.ref^, oper2.ref^);
+          else Result:=false;
+        end
+    end;
+
+
+  function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline;
+    begin
+      result := (oper.typ = top_reg) and (oper.reg = reg);
+    end;
+
+
+  function MatchInstruction(const instr: tai; const op: TAsmOp): boolean;
+    begin
+      result :=
+        (instr.typ = ait_instruction) and
+        (taicpu(instr).opcode = op);
+    end;
+
+
+  function MatchInstruction(const instr: tai; const ops: TAsmOpSet): boolean;
+    begin
+      result :=
+        (instr.typ = ait_instruction) and
+        (taicpu(instr).opcode in ops);
+    end;
+
+
+  function MatchInstruction(const instr: tai; const ops: TAsmOpSet;opcount : byte): boolean;
+    begin
+      result :=
+        (instr.typ = ait_instruction) and
+        (taicpu(instr).opcode in ops) and
+        (taicpu(instr).ops=opcount);
+    end;
+
+
+  function MatchOpType(const instr : tai;ot0,ot1 : toptype) : Boolean;
+    begin
+      Result:=(taicpu(instr).ops=2) and
+        (taicpu(instr).oper[0]^.typ=ot0) and
+        (taicpu(instr).oper[1]^.typ=ot1);
+    end;
+
+{$ifdef DEBUG_AOPTCPU}
+  procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
+    begin
+      asml.insertbefore(tai_comment.Create(strpnew(s)), p);
+    end;
+{$else DEBUG_AOPTCPU}
+  procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
+    begin
+    end;
+{$endif DEBUG_AOPTCPU}
+
+
+  function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
+    var Next: tai; reg: TRegister): Boolean;
+    begin
+      Next:=Current;
+      repeat
+        Result:=GetNextInstruction(Next,Next);
+      until not(cs_opt_level3 in current_settings.optimizerswitches) or not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
+        (is_calljmp(taicpu(Next).opcode));
+    end;
+
+
+  function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
+    //var
+    //  p: taicpu;
+    begin
+      inherited;
+      //if not assigned(hp) or
+      //   (hp.typ <> ait_instruction) then
+      // begin
+      //   Result := false;
+      //   exit;
+      // end;
+      //p := taicpu(hp);
+      //if SuperRegistersEqual(reg,NR_DEFAULTFLAGS) and (reg<>NR_AF) then
+      //  begin
+      //    case p.opcode of
+      //      A_PUSH,A_POP,A_EX,A_EXX,A_NOP,A_HALT,A_DI,A_EI,A_IM,A_SET,A_RES,A_JP,A_JR,A_JRJP,A_DJNZ,A_CALL,A_RET,A_RETI,A_RETN,A_RST,A_OUT:
+      //        result:=false;
+      //      A_LD:
+      //        begin
+      //          if p.ops<>2 then
+      //            internalerror(2020051112);
+      //          { LD A,I or LD A,R ? }
+      //          if (p.oper[0]^.typ=top_reg) and (p.oper[0]^.reg=NR_A) and
+      //             (p.oper[1]^.typ=top_reg) and ((p.oper[1]^.reg=NR_I) or (p.oper[1]^.reg=NR_R)) then
+      //            result:=(reg=NR_ADDSUBTRACTFLAG) or
+      //                    (reg=NR_PARITYOVERFLOWFLAG) or
+      //                    (reg=NR_HALFCARRYFLAG) or
+      //                    (reg=NR_ZEROFLAG) or
+      //                    (reg=NR_SIGNFLAG)
+      //          else
+      //            result:=false;
+      //        end;
+      //      A_LDI,A_LDIR,A_LDD,A_LDDR:
+      //        result:=(reg=NR_ADDSUBTRACTFLAG) or
+      //                (reg=NR_PARITYOVERFLOWFLAG) or
+      //                (reg=NR_HALFCARRYFLAG);
+      //      A_INC,A_DEC:
+      //        begin
+      //          if p.ops<>1 then
+      //            internalerror(2020051602);
+      //          if (p.oper[0]^.typ=top_reg) and ((p.oper[0]^.reg=NR_BC) or
+      //                                           (p.oper[0]^.reg=NR_DE) or
+      //                                           (p.oper[0]^.reg=NR_HL) or
+      //                                           (p.oper[0]^.reg=NR_SP) or
+      //                                           (p.oper[0]^.reg=NR_IX) or
+      //                                           (p.oper[0]^.reg=NR_IY)) then
+      //            result:=false
+      //          else
+      //            result:=(reg=NR_ADDSUBTRACTFLAG) or
+      //                    (reg=NR_PARITYOVERFLOWFLAG) or
+      //                    (reg=NR_HALFCARRYFLAG) or
+      //                    (reg=NR_ZEROFLAG) or
+      //                    (reg=NR_SIGNFLAG);
+      //        end;
+      //      A_CPI,A_CPIR,A_CPD,A_CPDR,A_RLD,A_RRD,A_BIT,A_INI,A_INIR,A_IND,A_INDR,A_OUTI,A_OTIR,A_OUTD,A_OTDR:
+      //        result:=(reg=NR_ADDSUBTRACTFLAG) or
+      //                (reg=NR_PARITYOVERFLOWFLAG) or
+      //                (reg=NR_HALFCARRYFLAG) or
+      //                (reg=NR_ZEROFLAG) or
+      //                (reg=NR_SIGNFLAG);
+      //      A_ADD:
+      //        begin
+      //          if p.ops<>2 then
+      //            internalerror(2020051601);
+      //          if (p.oper[0]^.typ=top_reg) and ((p.oper[0]^.reg=NR_HL) or (p.oper[0]^.reg=NR_IX) or (p.oper[0]^.reg=NR_IY)) then
+      //            result:=(reg=NR_HALFCARRYFLAG) or
+      //                    (reg=NR_ADDSUBTRACTFLAG) or
+      //                    (reg=NR_CARRYFLAG)
+      //          else
+      //            result:=true;
+      //        end;
+      //      A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP,A_NEG,A_RLC,A_RL,A_RRC,A_RR,A_SLA,A_SRA,A_SRL:
+      //        result:=true;
+      //      A_DAA:
+      //        result:=(reg=NR_PARITYOVERFLOWFLAG) or
+      //                (reg=NR_HALFCARRYFLAG) or
+      //                (reg=NR_ZEROFLAG) or
+      //                (reg=NR_SIGNFLAG) or
+      //                (reg=NR_CARRYFLAG);
+      //      A_CPL:
+      //        result:=(reg=NR_HALFCARRYFLAG) or
+      //                (reg=NR_ADDSUBTRACTFLAG);
+      //      A_CCF,A_SCF,A_RLCA,A_RLA,A_RRCA,A_RRA:
+      //        result:=(reg=NR_HALFCARRYFLAG) or
+      //                (reg=NR_ADDSUBTRACTFLAG) or
+      //                (reg=NR_CARRYFLAG);
+      //      A_IN:
+      //        begin
+      //          if p.ops<>2 then
+      //            internalerror(2020051612);
+      //          if (p.oper[1]^.typ=top_ref) and ((p.oper[1]^.ref^.base=NR_C) or (p.oper[1]^.ref^.index=NR_C)) then
+      //            result:=(reg=NR_ADDSUBTRACTFLAG) or
+      //                    (reg=NR_PARITYOVERFLOWFLAG) or
+      //                    (reg=NR_HALFCARRYFLAG) or
+      //                    (reg=NR_ZEROFLAG) or
+      //                    (reg=NR_SIGNFLAG)
+      //          else
+      //            result:=false;
+      //        end;
+      //      else
+      //        internalerror(2020051111);
+      //    end;
+      //  end
+      //else
+      //  case p.opcode of
+      //    A_LD:
+      //      begin
+      //        if p.ops<>2 then
+      //          internalerror(2020051114);
+      //        result:=(p.oper[0]^.typ = top_reg) and
+      //                (Reg1WriteOverwritesReg2Entirely(p.oper[0]^.reg,reg)) and
+      //                ((p.oper[1]^.typ = top_const) or
+      //                 ((p.oper[1]^.typ = top_reg) and not(Reg1ReadDependsOnReg2(p.oper[1]^.reg,reg))) or
+      //                 ((p.oper[1]^.typ = top_ref) and not RegInRef(reg,p.oper[1]^.ref^)));
+      //      end;
+      //    A_PUSH,A_EX,A_EXX,A_LDI,A_LDIR,A_LDD,A_LDDR,A_CPI,A_CPIR,A_CPD,A_CPDR,
+      //    A_ADD,A_ADC,A_SBC,A_CP,A_INC,A_DEC,A_DAA,A_CPL,A_NEG,A_CCF,A_SCF,
+      //    A_NOP,A_HALT,A_DI,A_EI,A_IM,A_RLCA,A_RLA,A_RRCA,A_RRA,A_RLC,A_RL,
+      //    A_RRC,A_RR,A_SLA,A_SRA,A_SRL,A_RLD,A_RRD,A_BIT,A_SET,A_RES,A_JP,A_JR,A_JRJP,
+      //    A_DJNZ,A_CALL,A_RET,A_RETI,A_RETN,A_RST,A_INI,A_INIR,A_IND,A_INDR,
+      //    A_OUT,A_OUTI,A_OTIR,A_OUTD,A_OTDR:
+      //      result:=false;
+      //    A_POP:
+      //      begin
+      //        if p.ops<>1 then
+      //          internalerror(2020051603);
+      //        if p.oper[0]^.typ<>top_reg then
+      //          internalerror(2020051604);
+      //        result:=Reg1WriteOverwritesReg2Entirely(p.oper[0]^.reg,reg);
+      //      end;
+      //    A_SUB,A_XOR:
+      //      begin
+      //        if p.ops<>2 then
+      //          internalerror(2020051605);
+      //        result:=(p.oper[0]^.typ=top_reg) and (p.oper[0]^.reg=NR_A) and
+      //                (p.oper[1]^.typ=top_reg) and (p.oper[1]^.reg=NR_A) and
+      //                Reg1WriteOverwritesReg2Entirely(NR_A,reg);
+      //      end;
+      //    A_AND:
+      //      begin
+      //        if p.ops<>2 then
+      //          internalerror(2020051606);
+      //        result:=(p.oper[0]^.typ=top_reg) and (p.oper[0]^.reg=NR_A) and
+      //                (p.oper[1]^.typ=top_const) and (p.oper[1]^.val=0) and
+      //                Reg1WriteOverwritesReg2Entirely(NR_A,reg);
+      //      end;
+      //    A_OR:
+      //      begin
+      //        if p.ops<>2 then
+      //          internalerror(2020051607);
+      //        result:=(p.oper[0]^.typ=top_reg) and (p.oper[0]^.reg=NR_A) and
+      //                (p.oper[1]^.typ=top_const) and (byte(p.oper[1]^.val)=255) and
+      //                Reg1WriteOverwritesReg2Entirely(NR_A,reg);
+      //      end;
+      //    A_IN:
+      //      begin
+      //        if p.ops<>2 then
+      //          internalerror(2020051608);
+      //        if p.oper[0]^.typ<>top_reg then
+      //          internalerror(2020051609);
+      //        if p.oper[1]^.typ<>top_ref then
+      //          internalerror(2020051610);
+      //        result:=Reg1WriteOverwritesReg2Entirely(p.oper[0]^.reg,reg) and
+      //                (((p.oper[1]^.ref^.base<>NR_C) and (p.oper[1]^.ref^.index<>NR_C)) or
+      //                 not(Reg1ReadDependsOnReg2(NR_BC,reg)));
+      //      end;
+      //    else
+      //      internalerror(2020051108);
+      //  end;
+    end;
+
+
+  function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
+    //var
+    //  p: taicpu;
+    begin
+      inherited;
+      //Result := false;
+      //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,A_JRJP:
+      //    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;
+    var
+      hp1,hp2,hp3,hp4,hp5: tai;
+      alloc, dealloc: tai_regalloc;
+      i: integer;
+      l: TAsmLabel;
+      //TmpUsedRegs : TAllUsedRegs;
+    begin
+      result := false;
+      //case p.typ of
+      //  ait_instruction:
+      //    begin
+      //    end;
+      //end;
+    end;
+
+
+  procedure TCpuAsmOptimizer.PeepHoleOptPass2;
+    begin
+    end;
+
+begin
+  casmoptimizer:=TCpuAsmOptimizer;
+End.

+ 52 - 0
compiler/mos6502/cpunode.pas

@@ -0,0 +1,52 @@
+{
+    Copyright (c) 2000-2017 by Florian Klaempfl
+
+    This unit includes the MOS Technology 6502 code generator into the compiler
+
+    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 cpunode;
+
+{$i fpcdefs.inc}
+
+  interface
+
+  implementation
+
+    uses
+       { generic nodes }
+       ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,ncgadd
+       { to be able to only parts of the generic code,
+         the processor specific nodes must be included
+         after the generic one (FK)
+       }
+       ,nmos6502add
+       ,nmos6502cal
+       ,nmos6502mat
+       ,nmos6502mem
+       ,nmos6502inl
+//       ,nmos6502cnv
+//       ,nmos6502util,
+       { these are not really nodes }
+       ,tgcpu
+       { symtable }
+       ,symcpu,
+       aasmdef
+       ;
+
+
+end.

+ 684 - 0
compiler/mos6502/nmos6502add.pas

@@ -0,0 +1,684 @@
+{
+    Copyright (c) 2008 by Florian Klaempfl
+
+    Code generation for add nodes on the MOS Technolog 6502
+
+    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 nmos6502add;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+       node,ncgadd, symtype,cpubase;
+
+    type
+
+       { TMOS6502AddNode }
+
+       TMOS6502AddNode = class(tcgaddnode)
+       //private
+       //  function GetResFlags(unsigned:Boolean;anodetype:tnodetype):TResFlags;
+       protected
+         function use_mul_helper: boolean;override;
+         function first_cmppointer: tnode;override;
+         function pass_1 : tnode;override;
+         procedure second_cmpordinal;override;
+         procedure second_cmpsmallset;override;
+         procedure second_cmp64bit;override;
+         //procedure second_cmp16_32_64bit;
+         procedure second_cmp;
+       end;
+
+  implementation
+
+    uses
+      globtype,systems,
+      cutils,verbose,globals,
+      symconst,symdef,paramgr,
+      aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+      cgbase,cgutils,cgcpu,
+      cpuinfo,pass_1,pass_2,procinfo,
+      cpupara,
+      ncon,nset,nadd,
+      ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32,
+      hlcgobj;
+
+{*****************************************************************************
+                               TMOS6502AddNode
+*****************************************************************************}
+
+
+    //function TMOS6502AddNode.GetResFlags(unsigned: Boolean; anodetype: tnodetype): TResFlags;
+    //  begin
+    //    case anodetype of
+    //      equaln:
+    //        GetResFlags:=F_E;
+    //      unequaln:
+    //        GetResFlags:=F_NE;
+    //      else
+    //        if not(unsigned) then
+    //          begin
+    //            { signed }
+    //            if nf_swapped in flags then
+    //              case anodetype of
+    //                ltn:
+    //                  GetResFlags:=F_NotPossible;
+    //                lten:
+    //                  GetResFlags:=F_P;
+    //                gtn:
+    //                  GetResFlags:=F_M;
+    //                gten:
+    //                  GetResFlags:=F_NotPossible;
+    //                else
+    //                  internalerror(2014082020);
+    //              end
+    //            else
+    //              case anodetype of
+    //                ltn:
+    //                  GetResFlags:=F_M;
+    //                lten:
+    //                  GetResFlags:=F_NotPossible;
+    //                gtn:
+    //                  GetResFlags:=F_NotPossible;
+    //                gten:
+    //                  GetResFlags:=F_P;
+    //                else
+    //                  internalerror(2014082021);
+    //              end;
+    //          end
+    //        else
+    //          begin
+    //            { unsigned }
+    //            if nf_swapped in Flags then
+    //              case anodetype of
+    //                ltn:
+    //                  GetResFlags:=F_NotPossible;
+    //                lten:
+    //                  GetResFlags:=F_NC;
+    //                gtn:
+    //                  GetResFlags:=F_C;
+    //                gten:
+    //                  GetResFlags:=F_NotPossible;
+    //                else
+    //                  internalerror(2014082022);
+    //              end
+    //            else
+    //              case anodetype of
+    //                ltn:
+    //                  GetResFlags:=F_C;
+    //                lten:
+    //                  GetResFlags:=F_NotPossible;
+    //                gtn:
+    //                  GetResFlags:=F_NotPossible;
+    //                gten:
+    //                  GetResFlags:=F_NC;
+    //                else
+    //                  internalerror(2014082023);
+    //              end;
+    //          end;
+    //    end;
+    //  end;
+
+
+    function TMOS6502AddNode.use_mul_helper: boolean;
+      begin
+        result:=(nodetype=muln);
+      end;
+
+
+    function TMOS6502AddNode.first_cmppointer: tnode;
+      begin
+        result:=nil;
+        expectloc:=LOC_JUMP;
+      end;
+
+
+    procedure TMOS6502AddNode.second_cmpsmallset;
+      begin
+        //case nodetype of
+        //  equaln,unequaln:
+        //    begin
+        //      if left.resultdef.size>=2 then
+        //        internalerror(2021100302);
+        //      second_cmp;
+        //    end;
+        //  lten,gten:
+        //    begin
+        //      if left.resultdef.size>=2 then
+        //        internalerror(2021100302);
+        //
+        //      pass_left_right;
+        //
+        //      if (not(nf_swapped in flags) and (nodetype = lten)) or
+        //         ((nf_swapped in flags) and (nodetype = gten)) then
+        //        swapleftright;
+        //
+        //      if left.location.loc<>LOC_REGISTER then
+        //        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+        //
+        //      if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+        //        begin
+        //          if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
+        //            begin
+        //              cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //              cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //              current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_AND,NR_A,right.location.reference));
+        //              current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_CP,NR_A,right.location.reference));
+        //              cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //            end
+        //          else
+        //            hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+        //        end;
+        //      case right.location.loc of
+        //        LOC_CONSTANT:
+        //          begin
+        //            cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //            cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_AND,NR_A,right.location.value));
+        //            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_CP,NR_A,right.location.value));
+        //            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          end;
+        //        LOC_REGISTER,LOC_CREGISTER:
+        //          begin
+        //            cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //            cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_AND,NR_A,right.location.register));
+        //            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_CP,NR_A,right.location.register));
+        //            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          end;
+        //        LOC_REFERENCE,LOC_CREFERENCE:
+        //          begin
+        //            { Already handled before the case statement. Nothing to do here. }
+        //          end;
+        //        else
+        //          internalerror(2021100303);
+        //      end;
+        //
+        //      location_reset(location,LOC_FLAGS,OS_NO);
+        //      location.resflags:=F_E;
+        //    end
+        //  else
+        //    internalerror(2021100301);
+        //end;
+      end;
+
+
+    procedure TMOS6502AddNode.second_cmp;
+      //var
+      //  unsigned : boolean;
+      //  tmpreg1,tmpreg2 : tregister;
+      //  i : longint;
+      //  opdef: tdef;
+      //  opsize: TCgSize;
+      //  l: TAsmLabel;
+      begin
+        //unsigned:=not(is_signed(left.resultdef)) or
+        //          not(is_signed(right.resultdef));
+        //opdef:=left.resultdef;
+        //opsize:=def_cgsize(opdef);
+        //
+        //pass_left_right;
+        //
+        //if (opsize=OS_8) or ((opsize=OS_S8) and (NodeType in [equaln,unequaln])) then
+        //  begin
+        //    if getresflags(unsigned,NodeType)=F_NotPossible then
+        //      swapleftright;
+        //
+        //    if left.location.loc<>LOC_REGISTER then
+        //      hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+        //
+        //    if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+        //      begin
+        //        if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
+        //          begin
+        //            cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //            cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_CP,NR_A,right.location.reference));
+        //            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          end
+        //        else
+        //          hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+        //      end;
+        //    case right.location.loc of
+        //      LOC_CONSTANT:
+        //        begin
+        //          cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //          current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_CP,NR_A,right.location.value));
+        //          cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //        end;
+        //      LOC_REGISTER,LOC_CREGISTER:
+        //        begin
+        //          cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //          current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_CP,NR_A,right.location.register));
+        //          cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //        end;
+        //      LOC_REFERENCE,LOC_CREFERENCE:
+        //        begin
+        //          { Already handled before the case statement. Nothing to do here. }
+        //        end;
+        //      else
+        //        internalerror(2020040402);
+        //    end;
+        //
+        //    location_reset(location,LOC_FLAGS,OS_NO);
+        //    location.resflags:=getresflags(unsigned,NodeType);
+        //  end
+        //else if opsize=OS_S8 then
+        //  begin
+        //    if getresflags(unsigned,NodeType)=F_NotPossible then
+        //      swapleftright;
+        //
+        //    if left.location.loc<>LOC_REGISTER then
+        //      hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+        //
+        //    if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+        //      begin
+        //        if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
+        //          begin
+        //            cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //            cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //            current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_SUB,NR_A,right.location.reference));
+        //          end
+        //        else
+        //          hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+        //      end;
+        //    case right.location.loc of
+        //      LOC_CONSTANT:
+        //        begin
+        //          cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //          current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SUB,NR_A,right.location.value));
+        //        end;
+        //      LOC_REGISTER,LOC_CREGISTER:
+        //        begin
+        //          cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //          cg.a_load_loc_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),left.location,NR_A);
+        //          current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_SUB,NR_A,right.location.register));
+        //        end;
+        //      LOC_REFERENCE,LOC_CREFERENCE:
+        //        begin
+        //          { Already handled before the case statement. Nothing to do here. }
+        //        end;
+        //      else
+        //        internalerror(2020040403);
+        //    end;
+        //    current_asmdata.getjumplabel(l);
+        //    cg.a_jmp_flags(current_asmdata.CurrAsmList,F_PO,l);
+        //    current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_XOR,NR_A,$80));
+        //    cg.a_label(current_asmdata.CurrAsmList,l);
+        //    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //
+        //    location_reset(location,LOC_FLAGS,OS_NO);
+        //    location.resflags:=getresflags(unsigned,NodeType);
+        //  end
+        //else
+        //  internalerror(2020040401);
+      end;
+
+
+    procedure TMOS6502AddNode.second_cmp64bit;
+      begin
+        //second_cmp16_32_64bit;
+      end;
+
+
+    //procedure TMOS6502AddNode.second_cmp16_32_64bit;
+    //  var
+    //    truelabel,
+    //    falselabel: tasmlabel;
+    //    unsigned  : boolean;
+    //    i, size: Integer;
+    //    tmpref: treference;
+    //    op: TAsmOp;
+    //    actualnodetype: tnodetype;
+    //  begin
+    //    truelabel:=nil;
+    //    falselabel:=nil;
+    //    pass_left_right;
+    //
+    //    unsigned:=not(is_signed(left.resultdef)) or
+    //              not(is_signed(right.resultdef));
+    //
+    //    { we have LOC_JUMP as result }
+    //    current_asmdata.getjumplabel(truelabel);
+    //    current_asmdata.getjumplabel(falselabel);
+    //    location_reset_jump(location,truelabel,falselabel);
+    //
+    //    size:=tcgsize2size[def_cgsize(left.resultdef)];
+    //
+    //    if NodeType in [equaln,unequaln] then
+    //      begin
+    //        if left.location.loc<>LOC_REGISTER then
+    //          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+    //
+    //        if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+    //          begin
+    //            if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
+    //              begin
+    //                cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //                tmpref:=right.location.reference;
+    //                for i:=0 to size-1 do
+    //                  begin
+    //                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
+    //                    current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(A_CP,NR_A,tmpref));
+    //                    case NodeType of
+    //                      equaln:
+    //                        if i<>(size-1) then
+    //                          cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,falselabel)
+    //                        else
+    //                          cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,truelabel);
+    //                      unequaln:
+    //                        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,truelabel);
+    //                      else
+    //                        internalerror(2020042102);
+    //                    end;
+    //                    if i<>(size-1) then
+    //                      tcgz80(cg).adjust_normalized_ref(current_asmdata.CurrAsmList,tmpref,1);
+    //                  end;
+    //                cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //                cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
+    //              end
+    //            else
+    //              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+    //          end;
+    //        case right.location.loc of
+    //          LOC_CONSTANT:
+    //            begin
+    //              cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              for i:=0 to size-1 do
+    //                begin
+    //                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
+    //                  current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_CP,NR_A,byte(right.location.value shr (i*8))));
+    //                  case NodeType of
+    //                    equaln:
+    //                      if i<>(size-1) then
+    //                        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,falselabel)
+    //                      else
+    //                        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,truelabel);
+    //                    unequaln:
+    //                      cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,truelabel);
+    //                    else
+    //                      internalerror(2020042104);
+    //                  end;
+    //                end;
+    //              cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
+    //            end;
+    //          LOC_REGISTER,LOC_CREGISTER:
+    //            begin
+    //              cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              for i:=0 to size-1 do
+    //                begin
+    //                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
+    //                  current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_CP,NR_A,tcgz80(cg).GetOffsetReg64(right.location.register,right.location.registerhi,i)));
+    //                  case NodeType of
+    //                    equaln:
+    //                      if i<>(size-1) then
+    //                        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,falselabel)
+    //                      else
+    //                        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,truelabel);
+    //                    unequaln:
+    //                      cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,truelabel);
+    //                    else
+    //                      internalerror(2020042105);
+    //                  end;
+    //                end;
+    //              cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel);
+    //            end;
+    //          LOC_REFERENCE,LOC_CREFERENCE:
+    //            begin
+    //              { Already handled before the case statement. Nothing to do here. }
+    //            end;
+    //          else
+    //            internalerror(2020042103);
+    //        end;
+    //      end
+    //    else
+    //      begin
+    //        if nf_swapped in Flags then
+    //          begin
+    //            case NodeType of
+    //              ltn:
+    //                actualnodetype:=gtn;
+    //              lten:
+    //                actualnodetype:=gten;
+    //              gtn:
+    //                actualnodetype:=ltn;
+    //              gten:
+    //                actualnodetype:=lten;
+    //              else
+    //                internalerror(2020042701);
+    //            end;
+    //          end
+    //        else
+    //          actualnodetype:=NodeType;
+    //
+    //        if left.location.loc<>LOC_REGISTER then
+    //          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+    //
+    //        if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+    //          begin
+    //            if is_ref_in_opertypes(right.location.reference,[OT_REF_IX_d,OT_REF_IY_d,OT_REF_HL]) then
+    //              begin
+    //                cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //                tmpref:=right.location.reference;
+    //                tcgz80(cg).adjust_normalized_ref(current_asmdata.CurrAsmList,tmpref,size-1);
+    //                for i:=size-1 downto 0 do
+    //                  begin
+    //                    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
+    //                    if (i=(size-1)) and (not unsigned) then
+    //                      op:=A_SUB
+    //                    else
+    //                      op:=A_CP;
+    //                    current_asmdata.CurrAsmList.Concat(taicpu.op_reg_ref(op,NR_A,tmpref));
+    //                    if (i=(size-1)) and (not unsigned) then
+    //                      case actualnodetype of
+    //                        ltn,
+    //                        lten:
+    //                          tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
+    //                        gtn,
+    //                        gten:
+    //                          tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
+    //                        else
+    //                          internalerror(2020042202);
+    //                      end
+    //                    else if i<>0 then
+    //                      case actualnodetype of
+    //                        ltn,
+    //                        lten:
+    //                          tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
+    //                        gtn,
+    //                        gten:
+    //                          tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
+    //                        else
+    //                          internalerror(2020042207);
+    //                      end
+    //                    else
+    //                      case actualnodetype of
+    //                        ltn:
+    //                          tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,falselabel,falselabel);
+    //                        lten:
+    //                          tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,truelabel,falselabel);
+    //                        gtn:
+    //                          tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,falselabel,truelabel);
+    //                        gten:
+    //                          tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,truelabel,truelabel);
+    //                        else
+    //                          internalerror(2020042203);
+    //                      end;
+    //                    if i<>0 then
+    //                      tcgz80(cg).adjust_normalized_ref(current_asmdata.CurrAsmList,tmpref,-1);
+    //                  end;
+    //                cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              end
+    //            else
+    //              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
+    //          end;
+    //        case right.location.loc of
+    //          LOC_CONSTANT:
+    //            begin
+    //              cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              for i:=size-1 downto 0 do
+    //                begin
+    //                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
+    //                  if (i=(size-1)) and (not unsigned) then
+    //                    op:=A_SUB
+    //                  else
+    //                    op:=A_CP;
+    //                  current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(op,NR_A,byte(right.location.value shr (i*8))));
+    //                  if (i=(size-1)) and (not unsigned) then
+    //                    case actualnodetype of
+    //                      ltn,
+    //                      lten:
+    //                        tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
+    //                      gtn,
+    //                      gten:
+    //                        tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
+    //                      else
+    //                        internalerror(2020042210);
+    //                    end
+    //                  else if i<>0 then
+    //                    case actualnodetype of
+    //                      ltn,
+    //                      lten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
+    //                      gtn,
+    //                      gten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
+    //                      else
+    //                        internalerror(2020042211);
+    //                    end
+    //                  else
+    //                    case actualnodetype of
+    //                      ltn:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,falselabel,falselabel);
+    //                      lten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,truelabel,falselabel);
+    //                      gtn:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,falselabel,truelabel);
+    //                      gten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,truelabel,truelabel);
+    //                      else
+    //                        internalerror(2020042215);
+    //                    end;
+    //                end;
+    //              cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //            end;
+    //          LOC_REGISTER,LOC_CREGISTER:
+    //            begin
+    //              cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //              for i:=size-1 downto 0 do
+    //                begin
+    //                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,tcgz80(cg).GetOffsetReg64(left.location.register,left.location.registerhi,i),NR_A);
+    //                  if (i=(size-1)) and (not unsigned) then
+    //                    op:=A_SUB
+    //                  else
+    //                    op:=A_CP;
+    //                  current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(op,NR_A,tcgz80(cg).GetOffsetReg64(right.location.register,right.location.registerhi,i)));
+    //                  if (i=(size-1)) and (not unsigned) then
+    //                    case actualnodetype of
+    //                      ltn,
+    //                      lten:
+    //                        tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
+    //                      gtn,
+    //                      gten:
+    //                        tcgz80(cg).a_jmp_signed_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
+    //                      else
+    //                        internalerror(2020042212);
+    //                    end
+    //                  else if i<>0 then
+    //                    case actualnodetype of
+    //                      ltn,
+    //                      lten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,nil,falselabel);
+    //                      gtn,
+    //                      gten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,nil,truelabel);
+    //                      else
+    //                        internalerror(2020042213);
+    //                    end
+    //                  else
+    //                    case actualnodetype of
+    //                      ltn:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,falselabel,falselabel);
+    //                      lten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,truelabel,truelabel,falselabel);
+    //                      gtn:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,falselabel,truelabel);
+    //                      gten:
+    //                        tcgz80(cg).a_jmp_unsigned_cmp_3way(current_asmdata.CurrAsmList,falselabel,truelabel,truelabel);
+    //                      else
+    //                        internalerror(2020042216);
+    //                    end;
+    //                end;
+    //              cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+    //            end;
+    //          LOC_REFERENCE,LOC_CREFERENCE:
+    //            begin
+    //              { Already handled before the case statement. Nothing to do here. }
+    //            end;
+    //          else
+    //            internalerror(2020042106);
+    //        end;
+    //      end;
+    //  end;
+
+
+    function TMOS6502AddNode.pass_1 : tnode;
+      begin
+        result:=inherited pass_1;
+{$ifdef dummy}
+        if not(assigned(result)) then
+          begin
+            unsigned:=not(is_signed(left.resultdef)) or
+              not(is_signed(right.resultdef));
+
+            if is_64bit(left.resultdef) and
+              ((nodetype in [equaln,unequaln]) or
+               (unsigned and (nodetype in [ltn,lten,gtn,gten]))
+              ) then
+              expectloc:=LOC_FLAGS;
+          end;
+        { handling boolean expressions }
+        if not(assigned(result)) and
+           (
+             not(is_boolean(left.resultdef)) or
+             not(is_boolean(right.resultdef)) or
+             is_dynamic_array(left.resultdef)
+           ) then
+          expectloc:=LOC_FLAGS;
+{$endif dummy}
+      end;
+
+
+    procedure TMOS6502AddNode.second_cmpordinal;
+      begin
+        //if left.resultdef.size>=2 then
+        //  second_cmp16_32_64bit
+        //else
+        //  second_cmp;
+      end;
+
+begin
+  caddnode:=TMOS6502AddNode;
+end.

+ 71 - 0
compiler/mos6502/nmos6502cal.pas

@@ -0,0 +1,71 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate MOS Technology 6502 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 nmos6502cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      ncgcal;
+
+    type
+       TMOS6502CallNode = class(tcgcallnode)
+       protected
+          procedure pop_parasize(pop_size:longint);override;
+       end;
+
+
+implementation
+
+    uses
+      cpubase,
+      aasmdata,aasmcpu,
+      ncal,
+      cgobj;
+
+
+{*****************************************************************************
+                             TMOS6502CallNode
+*****************************************************************************}
+
+
+    procedure TMOS6502CallNode.pop_parasize(pop_size:longint);
+      begin
+        //if pop_size>=2 then
+        //  begin
+        //    cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //    while pop_size>=2 do
+        //      begin
+        //        current_asmdata.CurrAsmList.Concat(taicpu.op_reg(A_POP,NR_AF));
+        //        dec(pop_size,2);
+        //      end;
+        //    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+        //  end;
+        //if pop_size=1 then
+        //  current_asmdata.CurrAsmList.Concat(taicpu.op_reg(A_INC,NR_SP));
+      end;
+
+
+begin
+   ccallnode:=TMOS6502CallNode;
+end.

+ 170 - 0
compiler/mos6502/nmos6502inl.pas

@@ -0,0 +1,170 @@
+{
+    Copyright (c) 2020 by Sven Barth
+
+    Generates MOS Technology 6502 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 nmos6502inl;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      node,ninl,ncginl, aasmbase;
+
+    type
+      TMOS6502InlineNode = class(tcginlinenode)
+//        function pass_typecheck_cpu:tnode;override;
+//        function first_cpu : tnode;override;
+//        procedure pass_generate_code_cpu;override;
+      end;
+
+  implementation
+
+    uses
+      compinnr,
+      aasmdata,
+      aasmcpu,
+      symdef,
+      defutil,
+      hlcgobj,
+      pass_2,
+      ncal,
+      cgbase, cgobj, cgutils,
+      cpubase;
+
+
+//    function TMOS6502InlineNode.pass_typecheck_cpu : tnode;
+//      begin
+//        Result:=nil;
+//        case inlinenumber of
+//          in_z80_inport:
+//            begin
+//              CheckParameters(1);
+//              resultdef:=u8inttype;
+//            end;
+//          in_z80_outport:
+//            begin
+//              CheckParameters(2);
+//              resultdef:=voidtype;
+//            end;
+//          else
+//            Result:=inherited pass_typecheck_cpu;
+//        end;
+//      end;
+
+
+//    function TMOS6502InlineNode.first_cpu : tnode;
+//      begin
+//        Result:=nil;
+//        case inlinenumber of
+//          in_z80_inport:
+//            expectloc:=LOC_REGISTER;
+//          in_z80_outport:
+//            expectloc:=LOC_VOID;
+//          else
+//            Result:=inherited first_cpu;
+//        end;
+//      end;
+
+
+//    procedure TMOS6502InlineNode.pass_generate_code_cpu;
+//
+//      procedure inport;
+//        var
+//          portnumber : tnode;
+//          dreg : tregister;
+//          ref : treference;
+//        begin
+//          portnumber:=left;
+//          secondpass(portnumber);
+//          if (portnumber.location.loc=LOC_CONSTANT) and
+//              (portnumber.location.value>=0) and
+//              (portnumber.location.value<=$ff) then
+//            begin
+//              { data needs to be put into A }
+//              dreg:=NR_A;
+//              reference_reset_base(ref,NR_NO,portnumber.location.value,ctempposinvalid,1,[]);
+//              current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_IN,dreg,ref));
+//            end
+//          else
+//            begin
+//              { data can be put anywhere, but port number must be in C }
+//              hlcg.getcpuregister(current_asmdata.CurrAsmList,NR_C);
+//              dreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_8);
+//              hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,portnumber.resultdef,u8inttype,portnumber.location,NR_C);
+//              reference_reset_base(ref,NR_C,0,ctempposinvalid,1,[]);
+//              current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_IN,dreg,ref));
+//              hlcg.ungetcpuregister(current_asmdata.CurrAsmList,NR_C);
+//            end;
+//            location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+//            location.register:=dreg;
+//        end;
+//
+//      procedure outport;
+//        var
+//          portnumber,
+//          portdata : tnode;
+//          dreg : tregister;
+//          ref : treference;
+//        begin
+//          portnumber:=tcallparanode(tcallparanode(left).right).left;
+//          portdata:=tcallparanode(left).left;
+//          secondpass(portdata);
+//          secondpass(portnumber);
+//          if (portnumber.location.loc=LOC_CONSTANT) and
+//              (portnumber.location.value>=0) and
+//              (portnumber.location.value<=$ff) then
+//            begin
+//              { data needs to reside in A }
+//              dreg:=NR_A;
+//              hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,portdata.resultdef,u8inttype,portdata.location,dreg);
+//              hlcg.getcpuregister(current_asmdata.CurrAsmList,dreg);
+//              reference_reset_base(ref,NR_NO,portnumber.location.value,ctempposinvalid,1,[]);
+//              current_asmdata.currasmlist.concat(taicpu.op_ref_reg(A_OUT,ref,dreg));
+//              hlcg.ungetcpuregister(current_asmdata.CurrAsmList,dreg);
+//            end
+//          else
+//            begin
+//              { data can reside anywhere, but port number must be in C }
+//              hlcg.getcpuregister(current_asmdata.CurrAsmList,NR_C);
+//              dreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_8);
+//              hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,portdata.resultdef,u8inttype,portdata.location,dreg);
+//              hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,portnumber.resultdef,u8inttype,portnumber.location,NR_C);
+//              reference_reset_base(ref,NR_C,0,ctempposinvalid,1,[]);
+//              current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_OUT,ref,dreg));
+//              hlcg.ungetcpuregister(current_asmdata.CurrAsmList,NR_C);
+//            end;
+//        end;
+//
+//      begin
+//        case inlinenumber of
+//          in_z80_inport:
+//            inport;
+//          in_z80_outport:
+//            outport;
+//          else
+//            inherited pass_generate_code_cpu;
+//        end;
+//      end;
+
+
+begin
+  cinlinenode:=TMOS6502InlineNode;
+end.

+ 152 - 0
compiler/mos6502/nmos6502mat.pas

@@ -0,0 +1,152 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate MOS Technology 6502 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 nmos6502mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      node,nmat,ncgmat;
+
+    type
+
+      { TMOS6502NotNode }
+
+      TMOS6502NotNode = class(tcgnotnode)
+      protected
+        procedure second_boolean;override;
+      end;
+
+
+implementation
+
+    uses
+      globtype,systems,constexp,
+      cutils,verbose,globals,
+      symconst,symdef,aasmbase,aasmtai,aasmdata,aasmcpu,defutil,
+      cgbase,pass_2,
+      ncon,
+      cpubase,cpuinfo,
+      ncgutil,cgobj,cgutils,
+      hlcgobj;
+
+{*****************************************************************************
+                                TMOS6502NotNode
+*****************************************************************************}
+
+
+    procedure TMOS6502NotNode.second_boolean;
+      //var
+      //  i: Integer;
+      begin
+//        secondpass(left);
+//        if not handle_locjump then
+//          begin
+//            if left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+//              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);
+//            case left.location.loc of
+//              LOC_FLAGS :
+//                begin
+//                  location_reset(location,LOC_FLAGS,OS_NO);
+//                  location.resflags:=left.location.resflags;
+//                  inverse_flags(location.resflags);
+//                end;
+//(*              LOC_CREFERENCE,
+//              LOC_REFERENCE:
+//                begin
+// {$if defined(cpu32bitalu)}
+//                  if is_64bit(resultdef) then
+//                    begin
+//                      hreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_32);
+//                      tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
+//                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hreg);
+//                      inc(left.location.reference.offset,4);
+//                      cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.reference,hreg);
+//                    end
+//                  else
+// {$elseif defined(cpu16bitalu)}
+//                  if is_64bit(resultdef) then
+//                    begin
+//                      hreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_16);
+//                      tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
+//                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,left.location.reference,hreg);
+//                      inc(left.location.reference.offset,2);
+//                      cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_16,left.location.reference,hreg);
+//                      inc(left.location.reference.offset,2);
+//                      cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_16,left.location.reference,hreg);
+//                      inc(left.location.reference.offset,2);
+//                      cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_16,left.location.reference,hreg);
+//                    end
+//                  else if is_32bit(resultdef) then
+//                    begin
+//                      hreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_16);
+//                      tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
+//                      cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,left.location.reference,hreg);
+//                      inc(left.location.reference.offset,2);
+//                      cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_16,left.location.reference,hreg);
+//                    end
+//                  else
+// {$endif}
+//                    emit_const_ref(A_CMP, TCGSize2Opsize[opsize], 0, left.location.reference);
+//                  location_reset(location,LOC_FLAGS,OS_NO);
+//                  location.resflags:=F_E;
+//                end;*)
+//              LOC_CONSTANT,
+//              LOC_REGISTER,
+//              LOC_CREGISTER,
+//              LOC_SUBSETREG,
+//              LOC_CSUBSETREG,
+//              LOC_SUBSETREF,
+//              LOC_CSUBSETREF :
+//                begin
+//                  if tcgsize2size[def_cgsize(left.resultdef)]<>tcgsize2size[def_cgsize(resultdef)] then
+//                    internalerror(2020042209);
+//                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);
+//                  if tcgsize2size[def_cgsize(left.resultdef)]=1 then
+//                    begin
+//                      cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+//                      cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,left.location.register,NR_A);
+//                      current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_OR,NR_A,NR_A));
+//                      cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+//                    end
+//                  else
+//                    begin
+//                      cg.getcpuregister(current_asmdata.CurrAsmList,NR_A);
+//                      cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,left.location.register,NR_A);
+//                      for i:=1 to tcgsize2size[def_cgsize(left.resultdef)]-1 do
+//                        current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_OR,NR_A,cg.GetOffsetReg64(left.location.register,left.location.registerhi,i)));
+//                      cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_A);
+//                    end;
+//                  location_reset(location,LOC_FLAGS,OS_NO);
+//                  location.resflags:=F_E;
+//                end;
+//              else
+//                internalerror(2020042208);
+//            end;
+//          end;
+      end;
+
+
+begin
+   cnotnode:=TMOS6502NotNode;
+end.

+ 71 - 0
compiler/mos6502/nmos6502mem.pas

@@ -0,0 +1,71 @@
+{
+    Copyright (c) 1998-2002 by Florian Klaempfl
+
+    Generate MOS Technology 6502 assembler for in memory related 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 nmos6502mem;
+
+{$i fpcdefs.inc}
+
+interface
+
+    uses
+      cgbase,cpubase,
+      nmem,ncgmem;
+
+    type
+
+       { TMOS6502LoadParentFPNode }
+
+       TMOS6502LoadParentFPNode = class(tcgloadparentfpnode)
+         procedure pass_generate_code;override;
+       end;
+
+implementation
+
+    uses
+      aasmdata,aasmcpu,
+      cgobj;
+
+
+{*****************************************************************************
+                            TMOS6502LoadParentFPNode
+*****************************************************************************}
+
+      procedure TMOS6502LoadParentFPNode.pass_generate_code;
+        begin
+          inherited pass_generate_code;
+          //if (location.loc=LOC_REGISTER) and ((location.register=NR_IX) or (location.register=NR_IY)) then
+          //  begin
+          //    cg.getcpuregister(current_asmdata.CurrAsmList,NR_H);
+          //    cg.getcpuregister(current_asmdata.CurrAsmList,NR_L);
+          //    current_asmdata.CurrAsmList.Concat(taicpu.op_reg(A_PUSH,location.register));
+          //    current_asmdata.CurrAsmList.Concat(taicpu.op_reg(A_POP,NR_HL));
+          //    location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
+          //    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,NR_L,location.register);
+          //    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_L);
+          //    cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_8,OS_8,NR_H,cg.GetNextReg(location.register));
+          //    cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_H);
+          //  end;
+        end;
+
+
+begin
+  cloadparentfpnode:=TMOS6502LoadParentFPNode;
+end.