Changeset 10 for trunk/Z80/Z80.pas


Ignore:
Timestamp:
Apr 20, 2026, 9:52:45 PM (6 days ago)
Author:
chronos
Message:
  • Added: Decoding area of instructions with two prefixes.
  • Modified: Improved parameter handling in disassembler.
  • Modified: Improving handling of flags.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Z80/Z80.pas

    r9 r10  
    5757    MessageText: string;
    5858    procedure Error(Message: string);
     59    function GetCarry: Boolean;
     60    function GetParityOverflow: Boolean;
     61    function GetSignNegative: Boolean;
     62    function GetZero: Boolean;
     63    procedure SetCarry(AValue: Boolean);
     64    procedure SetParityOverflow(AValue: Boolean);
     65    procedure SetSignNegative(AValue: Boolean);
     66    procedure SetZero(AValue: Boolean);
    5967    procedure SetRunning(AValue: Boolean);
    6068    function DoRead(Address: Word): Byte;
     
    7280    procedure Call(Address: Word);
    7381    procedure CallCond(Address: Word; Condition: Boolean);
    74     procedure Cp(Data: Byte);
     82    procedure CpByte(Data: Byte);
    7583    procedure Jr(Condition: Boolean);
    7684    procedure Jp(Condition: Boolean);
     
    808816    RegI: Byte;
    809817    RegR: Byte;
    810     Carry: Boolean;
    811     Zero: Boolean;
    812     ParityOverflow: Boolean;
    813     SignNegative: Boolean;
    814818    Memory: TMemory;
    815819    Ticks: Cardinal;
     
    823827    constructor Create;
    824828    destructor Destroy; override;
     829    property Carry: Boolean read GetCarry write SetCarry;
     830    property Zero: Boolean read GetZero write SetZero;
     831    property ParityOverflow: Boolean read GetParityOverflow
     832      write SetParityOverflow;
     833    property SignNegative: Boolean read GetSignNegative write SetSignNegative;
    825834    property Thread: TCpuThread read FThread;
    826835    property Running: Boolean read FRunning write SetRunning;
     
    858867  DoMessage(Message + ' on address ' + IntToHex(Word(PC), 4));
    859868  Halt;
     869end;
     870
     871function TCpuZ80.GetCarry: Boolean;
     872begin
     873  Result := (AF.F and $1) <> 0;
     874end;
     875
     876function TCpuZ80.GetParityOverflow: Boolean;
     877begin
     878  Result := (AF.F and $4) <> 0;
     879end;
     880
     881function TCpuZ80.GetSignNegative: Boolean;
     882begin
     883  Result := (AF.F and $80) <> 0;
     884end;
     885
     886function TCpuZ80.GetZero: Boolean;
     887begin
     888  Result := (AF.F and $40) <> 0;
     889end;
     890
     891procedure TCpuZ80.SetCarry(AValue: Boolean);
     892begin
     893  AF.F := (AF.F and $fe) or Byte(AValue);
     894end;
     895
     896procedure TCpuZ80.SetParityOverflow(AValue: Boolean);
     897begin
     898  AF.F := (AF.F and $fb) or (Byte(AValue) shl 2);
     899end;
     900
     901procedure TCpuZ80.SetSignNegative(AValue: Boolean);
     902begin
     903  AF.F := (AF.F and $7f) or (Byte(AValue) shl 7);
     904end;
     905
     906procedure TCpuZ80.SetZero(AValue: Boolean);
     907begin
     908  AF.F := (AF.F and $bf) or (Byte(AValue) shl 6);
    860909end;
    861910
     
    9681017end;
    9691018
    970 procedure TCpuZ80.Cp(Data: Byte);
     1019procedure TCpuZ80.CpByte(Data: Byte);
    9711020var
    972   TempByte: Byte;
    973 begin
    974   Carry := Data > AF.A;
    975   TempByte := Byte(ShortInt(AF.A) - ShortInt(Data));
    976   Zero := TempByte = 0;
     1021  Temp: Byte;
     1022begin
     1023  Temp := AF.A;
     1024  SubByte(Temp, Data);
    9771025end;
    9781026
     
    10111059
    10121060procedure TCpuZ80.AddByte(var Target: Byte; Second: Byte);
    1013 begin
    1014   Target := Byte(Target + Second);
     1061var
     1062  Temp: Word;
     1063begin
     1064  Temp := Target + Second;
     1065  ParityOverflow := ((Target and $80) = (Second and $80)) and
     1066    ((Target and $80) <> (Temp and $80));
     1067  Carry := (Temp and $100) <> 0;
     1068  Zero := Byte(Temp) = 0;
     1069  SignNegative := (Temp and $80) <> 0;
     1070  Target := Byte(Temp);
    10151071end;
    10161072
    10171073procedure TCpuZ80.AddWord(var Target: Word; Second: Word);
    1018 begin
    1019   Target := Word(Target + Second);
     1074var
     1075  Temp: Cardinal;
     1076begin
     1077  Temp := Target + Second;
     1078  Carry := Temp > $ffff;
     1079  Target := Word(Temp + Second);
    10201080end;
    10211081
    10221082procedure TCpuZ80.AdcByte(var Target: Byte; Second: Byte);
    1023 begin
    1024   Target := Target + Second;
     1083var
     1084  Temp: Word;
     1085begin
     1086  Temp := Target + Second + Byte(Carry);
     1087  ParityOverflow := ((Target and $80) = (Second and $80)) and
     1088    ((Target and $80) <> (Temp and $80));
     1089  Carry := (Temp and $100) <> 0;
     1090  Zero := Byte(Temp) = 0;
     1091  SignNegative := (Temp and $80) <> 0;
     1092  Target := Byte(Temp);
    10251093end;
    10261094
    10271095procedure TCpuZ80.AdcWord(var Target: Word; Second: Word);
    1028 begin
    1029   Target := Target - Second;
     1096var
     1097  Temp: Cardinal;
     1098begin
     1099  Temp := Target + Second + Byte(Carry);
     1100  Carry := Temp > $ffff;
     1101  Target := Word(Temp + Second);
    10301102end;
    10311103
    10321104procedure TCpuZ80.SubByte(var Target: Byte; Second: Byte);
    1033 begin
    1034   Target := Byte(Target - Second);
     1105var
     1106  Temp: SmallInt;
     1107begin
     1108  Temp := ShortInt(Target) - ShortInt(Second);
     1109  ParityOverflow := ((Target and $80) <> (Second and $80)) and
     1110    ((Target and $80) <> (Temp and $80));
     1111  Carry := (Temp and $100) <> 0;
     1112  Zero := Byte(Temp) = 0;
     1113  SignNegative := (Temp and $80) <> 0;
     1114  Target := Byte(Temp);
    10351115end;
    10361116
    10371117procedure TCpuZ80.SbcByte(var Target: Byte; Second: Byte);
    1038 begin
    1039   Target := Target - Second;
     1118var
     1119  Temp: SmallInt;
     1120begin
     1121  Temp := ShortInt(Target) - ShortInt(Second) - Byte(Carry);
     1122  ParityOverflow := ((Target and $80) <> (Second and $80)) and
     1123    ((Target and $80) <> (Temp and $80));
     1124  Carry := (Temp and $100) <> 0;
     1125  Zero := Byte(Temp) = 0;
     1126  SignNegative := (Temp and $80) <> 0;
     1127  Target := Byte(Temp);
    10401128end;
    10411129
    10421130procedure TCpuZ80.SbcWord(var Target: Word; Second: Word);
    1043 begin
    1044   Target := Target - Second;
     1131var
     1132  Temp: Integer;
     1133begin
     1134  Temp := SmallInt(Target) - SmallInt(Second);
     1135  ParityOverflow := ((Target and $8000) <> (Second and $8000)) and
     1136    ((Target and $8000) <> (Temp and $8000));
     1137  Carry := (Temp and $10000) <> 0;
     1138  Zero := Word(Temp) = 0;
     1139  SignNegative := (Temp and $8000) <> 0;
     1140  Target := Word(Temp);
    10451141end;
    10461142
     
    10481144begin
    10491145  Target := Target xor Second;
     1146  Carry := False;
     1147  Zero := Target = 0;
     1148  ParityOverflow := not Odd(Target);
     1149  SignNegative := (Target and $80) <> 0;
    10501150end;
    10511151
     
    10531153begin
    10541154  Target := Target or Second;
     1155  Carry := False;
     1156  Zero := Target = 0;
     1157  ParityOverflow := not Odd(Target);
     1158  SignNegative := (Target and $80) <> 0;
    10551159end;
    10561160
     
    10581162begin
    10591163  Target := Target and Second;
     1164  Carry := False;
     1165  Zero := Target = 0;
     1166  ParityOverflow := not Odd(Target);
     1167  SignNegative := (Target and $80) <> 0;
    10601168end;
    10611169
    10621170procedure TCpuZ80.IncByte(var Reg: Byte);
    10631171begin
     1172  ParityOverflow := Reg = $7f;
     1173
    10641174  if Reg = High(Reg) then Reg := 0
    10651175    else Inc(Reg);
     1176
     1177  Zero := Reg = 0;
     1178  SignNegative := (Reg and $80) <> 0;
    10661179end;
    10671180
     
    10741187procedure TCpuZ80.DecByte(var Reg: Byte);
    10751188begin
     1189  ParityOverflow := Reg = $80;
     1190
    10761191  if Reg = 0 then Reg := High(Reg)
    1077     else Dec(Reg)
     1192    else Dec(Reg);
     1193
     1194  Zero := Reg = 0;
     1195  SignNegative := (Reg and $80) <> 0;
    10781196end;
    10791197
     
    10811199begin
    10821200  if Reg = 0 then Reg := High(Reg)
    1083     else Dec(Reg)
     1201    else Dec(Reg);
    10841202end;
    10851203
     
    10871205begin
    10881206  Carry := (Data and $80) <> 0;
    1089   Data := (Data shl 1) or Byte(Carry);
     1207  Data := ((Data shl 1) and $ff) or Byte(Carry);
    10901208end;
    10911209
     
    18842002  Temp: ShortInt;
    18852003begin
    1886   Dec(BC.B);
     2004  if BC.B = 0 then BC.B := $ff
     2005    else Dec(BC.B);
    18872006  Temp := ShortInt(ReadByte);
    18882007  if BC.B <> 0 then
     
    27432862procedure TCpuZ80.CP_B;
    27442863begin
    2745   Cp(BC.B);
     2864  CpByte(BC.B);
    27462865end;
    27472866
    27482867procedure TCpuZ80.CP_C;
    27492868begin
    2750   Cp(BC.C);
     2869  CpByte(BC.C);
    27512870end;
    27522871
    27532872procedure TCpuZ80.CP_D;
    27542873begin
    2755   Cp(DE.D);
     2874  CpByte(DE.D);
    27562875end;
    27572876
    27582877procedure TCpuZ80.CP_E;
    27592878begin
    2760   Cp(DE.E);
     2879  CpByte(DE.E);
    27612880end;
    27622881
    27632882procedure TCpuZ80.CP_H;
    27642883begin
    2765   Cp(HL.H);
     2884  CpByte(HL.H);
    27662885end;
    27672886
    27682887procedure TCpuZ80.CP_L;
    27692888begin
    2770   Cp(HL.L);
     2889  CpByte(HL.L);
    27712890end;
    27722891
    27732892procedure TCpuZ80.CP_HL_Indirect;
    27742893begin
    2775   CP(DoRead(HL.Value));
     2894  CpByte(DoRead(HL.Value));
    27762895end;
    27772896
    27782897procedure TCpuZ80.CP_A;
    27792898begin
    2780   CP(AF.A);
     2899  CpByte(AF.A);
    27812900end;
    27822901
     
    30913210procedure TCpuZ80.CP_N;
    30923211begin
    3093   Cp(ReadByte);
     3212  CpByte(ReadByte);
    30943213end;
    30953214
     
    31213240procedure TCpuZ80.NEG;
    31223241begin
     3242  ParityOverflow := AF.A = $80;
     3243  Carry := AF.A <> $0;
    31233244  AF.A := AF.A xor $ff;
    31243245  IncByte(AF.A);
     3246  SignNegative := (AF.A and $80) <> 1;
     3247  Zero := AF.A = 0;
    31253248end;
    31263249
     
    33123435procedure TCpuZ80.CPI;
    33133436begin
    3314   Cp(DoRead(HL.Value));
     3437  CpByte(DoRead(HL.Value));
    33153438  IncWord(HL.Value);
    33163439  DecWord(BC.Value);
     
    33413464procedure TCpuZ80.CPD;
    33423465begin
    3343   Cp(DoRead(HL.Value));
     3466  CpByte(DoRead(HL.Value));
    33443467  DecWord(HL.Value);
    33453468  DecWord(BC.Value);
     
    53725495  Opcode := ReadByte;
    53735496  if Opcode = $CB then begin
     5497    Opcode := ReadByte;
    53745498    Instruction := TInstruction($100 or ReadByte);
    53755499  end
    53765500  else if Opcode = $DD then begin
    5377     Instruction := TInstruction($200 or ReadByte);
     5501    Opcode := ReadByte;
     5502    if Opcode = $CB then begin
     5503      Opcode := ReadByte;
     5504      Instruction := TInstruction($500 or Opcode);
     5505    end else Instruction := TInstruction($200 or Opcode);
    53785506  end
    53795507  else if Opcode = $ED then begin
    5380     Instruction := TInstruction($300 or ReadByte);
     5508    Opcode := ReadByte;
     5509    Instruction := TInstruction($300 or Opcode);
    53815510  end
    53825511  else if Opcode = $FD then begin
    5383     Instruction := TInstruction($400 or ReadByte);
     5512    Opcode := ReadByte;
     5513    if Opcode = $CB then begin
     5514      Opcode := ReadByte;
     5515      Instruction := TInstruction($600 or Opcode);
     5516    end else Instruction := TInstruction($400 or Opcode);
    53845517  end
    53855518  else Instruction := TInstruction(Opcode);
Note: See TracChangeset for help on using the changeset viewer.