Общие сведения о программе
Программа KP580BM80 моделирует работу микропроцессора К580 при выполнении команд обмена между памятью и регистрами, логических операций, арифметических операций, команд передачи управления и команд управления процессором.
Для ввода программного кода можно использовать упрощенный язык ассемблера или вводить программу непосредственно в машинных кодах в ячейки памяти. При использовании языка ассемблера можно заранее подготовить текст, например в «Блокноте» (Note Book), и загрузить этот код в память. Можно также написать программу на языке ассемблера воспользовавшись полем редактирования кода в окне программы.
Выполнение введенной программы осуществляется по шагам. При этом результат выполнения каждого шага отображается в поле вывода результатов трассировки.
Скриншот программы:
Текст программы:
KP580BM80.dpr
program KP580BM80;
uses
Forms,
MainForm in 'MainForm.pas' {K580MainForm},
AsmUnit in 'AsmUnit.pas',
MPUnit in 'MPUnit.pas';
{$R *.res}
begin
Application.Initialize;
Application.HelpFile := '\Help\KP580BM80.HLP';
Application.Title := 'Эмулятор микропроцессора К580';
Application.CreateForm(TK580MainForm, K580MainForm);
Application.Run;
end.
MainForm.pas
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus, Grids, ComCtrls, MPUnit, AsmUnit, ToolWin,
ImgList, ActnList;
type
TK580MainForm = class(TForm)
MainMenu: TMainMenu;
FileMenu: TMenuItem;
LoadMenu: TMenuItem;
LoadDialog: TOpenDialog;
MemGrid: TDrawGrid;
MemLabel: TLabel;
ComEditLabel: TLabel;
StatusBar: TStatusBar;
RegLabel: TLabel;
RegGrid: TDrawGrid;
PCSPGrid: TStringGrid;
CodeMemo: TMemo;
RezMemo: TMemo;
SaveMenu: TMenuItem;
JustDoItMenu: TMenuItem;
TraseMenu: TMenuItem;
ApplyMenu: TMenuItem;
AboutMenu: TMenuItem;
HelpMenu: TMenuItem;
SaveDialog: TSaveDialog;
SimpleLine1: TMenuItem;
ExitMenu: TMenuItem;
SaveCodeMenu: TMenuItem;
PortsGrid: TDrawGrid;
PortsLabel: TLabel;
ToolBar: TToolBar;
LoadBtn: TToolButton;
SaveCodeBtn: TToolButton;
SaveBtn: TToolButton;
Separator1: TToolButton;
ApplyBtn: TToolButton;
TraceBtn: TToolButton;
Separator2: TToolButton;
ExecBtn: TToolButton;
BreakMenu: TMenuItem;
ExecMenu: TMenuItem;
SimpleLine2: TMenuItem;
BreakBtn: TToolButton;
Separator3: TToolButton;
HelpBtn: TToolButton;
ToolImageList: TImageList;
ActionList: TActionList;
LoadAction: TAction;
SaveCodeAction: TAction;
SaveAction: TAction;
ExitAction: TAction;
ApplyAction: TAction;
TraceAction: TAction;
ExecAction: TAction;
BreakAction: TAction;
HelpAction: TAction;
SimpleLine3: TMenuItem;
ClearRezultsMenu: TMenuItem;
ClearRezultsAction: TAction;
ClearRezultsBtn: TToolButton;
ClearMemMenu: TMenuItem;
ClearMemAction: TAction;
ClearMemBtn: TToolButton;
procedure MainFormClose(Sender: TObject; var Action: TCloseAction);
procedure MainFormCreate(Sender: TObject);
procedure MainFormDestroy(Sender: TObject);
procedure GridKeyPress(Sender: TObject; var Key: Char);
procedure MemGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure MemGridGetEditMask(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure MemGridGetEditText(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure MemGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure MemGridSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
procedure RegGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure RegGridGetEditMask(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure RegGridGetEditText(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure RegGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure RegGridSelectSell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
procedure PCSPGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure PCSPGridGetEditMask(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure PCSPGridGetEditText(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure PCSPGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure PortsGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure PortsGridGetEditMask(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure PortsGridGetEditText(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure PortsGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure LoadMenuClick(Sender: TObject);
procedure ApplyMenuClick(Sender: TObject);
procedure SaveMenuClick(Sender: TObject);
procedure HelpMenuClick(Sender: TObject);
procedure SaveCodeMenuClick(Sender: TObject);
procedure MainFormCloseClick(Sender: TObject);
procedure TraceMenuClick(Sender: TObject);
procedure BreakMenuClick(Sender: TObject);
procedure ExecMenuClick(Sender: TObject);
procedure ClearRezultsMenuClick(Sender: TObject);
procedure ClearMemMenuClick(Sender: TObject);
private
Reg: TK580Regs;
Mem: PByteList;
Ports: PByteList;
Run: Boolean;
Int: Boolean;
CmdInfo: TCmdInfo;
{ Private declarations }
public
function GetWordFromMem(Addr: Word): Word;//Получить слово из памяти.
function GetNextWordFromMem(Addr: Word): Word;//Получить следующие после Addr слово.
function GetRunString: string;
function GetIntString: string;
function GetUseMem: Boolean;
function GetWordMem: Boolean;
function GetMemAddr: Word;
function HexToInt(Hex: string): Integer;
function IntToBin(Int: Byte): string; overload;
function IntToBin(Int: Word): string; overload;
procedure RunThreadTerminate(Sender: TObject);
{ Public declarations }
end;
var
K580MainForm: TK580MainForm;
K580Thread: TK580MP;
implementation
{$R *.dfm}
function TK580MainForm.GetWordFromMem(Addr: Word): Word;
begin
if Addr < 65535
then
GetWordFromMem := (Mem[Addr + 1] shl 8) + Mem[Addr]
else
GetWordFromMem := (Mem[0] shl 8) + Mem[Addr];
end;
function TK580MainForm.GetNextWordFromMem(Addr: Word): Word;
begin
if Addr = 65535
then Addr := 0
else Addr := Addr + 1;
GetNextWordFromMem := GetWordFromMem(Addr);
end;
function TK580MainForm.GetRunString: string;
begin
if Run
then GetRunString := 'Running'
else GetRunString := 'Stopped';
end;
function TK580MainForm.GetIntString: string;
begin
if Int
then GetIntString := 'Yes'
else GetIntString := 'No';
end;
function TK580MainForm.GetUseMem: Boolean;
begin
GetUseMem := CmdInfo.UseMem;
end;
function TK580MainForm.GetWordMem: Boolean;
begin
GetWordMem := CmdInfo.WordMem;
end;
function TK580MainForm.GetMemAddr: Word;
begin
GetMemAddr := CmdInfo.MemAddr;
end;
function TK580MainForm.HexToInt(Hex: string): Integer;
var
N, A, i, Len: Integer;
Chr: Char;
begin
N := 0;
Len := Length(Hex);
for i := 1 to Len do
begin
Chr := UpCase(Hex[i]);
if (Chr >= '0') and (Chr <= '9')
then A := Ord(Chr) - Ord('0')
else
if (Chr >= 'A') and (Chr <= 'F')
then A := Ord(Chr) - Ord('A') + 10
else A := 0;
N := (N shl 4) + A;
end;
HexToInt := N;
end;
function TK580MainForm.IntToBin(Int: Byte): string;
var
i, R: Integer;
Str: string;
begin
Str := '0000 0000';
i := 9;
while Int <> 0 do
begin
R := Int and $01;
if R = 1
then Str[i] := '1';
Int := Int shr 1;
i := i - 1;
if i = 5 then i := 4;
end;
IntToBin := Str;
end;
function TK580MainForm.IntToBin(Int: Word): string;
var
i, R: Integer;
Str: string;
begin
Str := '0000 0000 0000 0000';
i := 21;
while Int <> 0 do
begin
R := Int and $01;
if R = 1
then Str[i] := '1';
Int := Int shr 1;
i := i - 1;
if (i = 5) or (i = 17)
then i := i - 1
else
if (i = 12)
then i := 9;
end;
IntToBin := Str;
end;
procedure TK580MainForm.MainFormClose(Sender: TObject;
var Action: TCloseAction);
begin
Application.Terminate;
end;
procedure TK580MainForm.MainFormCreate(Sender: TObject);
begin
CmdInfo.LastAddr := 0;
CmdInfo.LastCmd := 0;
CmdInfo.LastTag := 0;
CmdInfo.UseMem := False;
CmdInfo.WordMem := False;
CmdInfo.Contents := '';
Reg.PC := 0;
Reg.SP := 0;
Reg.PSW := 0;
Reg.BC := 0;
Reg.DE := 0;
Reg.HL := 0;
Run := False;
Int := True;
SetLength(Mem,65536);
SetLength(Ports,256);
MemGrid.ColWidths[0] := 16;
MemGrid.ColWidths[1] := 80;
MemGrid.ColWidths[2] := 32;
MemGrid.ColWidths[3] := 32;
MemGrid.ColWidths[4] := 48;
MemGrid.Col := 4;
RegGrid.ColWidths[0] := 32;
RegGrid.ColWidths[1] := 87;
RegGrid.ColWidths[2] := 87;
PCSPGrid.ColWidths[0] := 32;
PCSPGrid.ColWidths[1] := 175;
PortsGrid.ColWidths[0] := 32;
PortsGrid.ColWidths[1] := 32;
StatusBar.Panels[2].Text := GetRunString;
StatusBar.Panels[3].Text := GetIntString;
BreakAction.Enabled := False;
end;
procedure TK580MainForm.MainFormDestroy(Sender: TObject);
begin
if K580Thread <> nil
then K580Thread.Terminate;
Mem := nil;
Ports := nil;
CmdInfo.Contents := '';
end;
procedure TK580MainForm.GridKeyPress(Sender: TObject; var Key: Char);
begin
if ((Key > 'F') and (Key <= 'Z')) or ((Key > 'f') and (Key <= 'z'))
or (Key > #127)
then Key := #0;
end;
procedure TK580MainForm.MemGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if ARow > 0
then
begin
if (ACol > 1) and (ACol < 4)
then
begin
MemGrid.Canvas.Pen.Color := clRed;
if GetUseMem
then
if (((ARow - 1) shl 1) + ACol - 2) = GetMemAddr
then
begin
MemGrid.Canvas.Pen.Color := clYellow;
MemGrid.Canvas.Brush.Color := clYellow;
MemGrid.Canvas.Rectangle(Rect);
end
else
if ((((ARow - 1) shl 1) + ACol - 3) = GetMemAddr) and
GetWordMem
then
begin
MemGrid.Canvas.Pen.Color := clYellow;
MemGrid.Canvas.Brush.Color := clYellow;
MemGrid.Canvas.Rectangle(Rect);
end;
if (((ARow - 1) shl 1) + ACol - 2) = Reg.PC
then
begin
MemGrid.Canvas.Brush.Color := clRed;
MemGrid.Canvas.Rectangle(Rect);
end;
end;
case ACol of
1:
MemGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
IntToHex((ARow shl 1) - 2, 4) + ':' + IntToHex((ARow shl 1) - 1, 4));
2:
MemGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
IntToHex(Mem[(ARow shl 1) - 2], 2));
3:
MemGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
IntToHex(Mem[(ARow shl 1) - 1], 2));
4:
begin
if (((ARow - 1) shl 1) = GetMemAddr) and
GetWordMem
then
begin
MemGrid.Canvas.Pen.Color := clYellow;
MemGrid.Canvas.Brush.Color := clYellow;
MemGrid.Canvas.Rectangle(Rect);
end;
MemGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
IntToHex(((Mem[(ARow shl 1) - 1] shl 8) +
Mem[(ARow shl 1) - 2]), 4));
end;
else
if ARow = (Reg.PC shr 1) + 1
then
begin
MemGrid.Canvas.Pen.Color := clBlue;
MemGrid.Canvas.Brush.Color := clBlue;
MemGrid.Canvas.Polygon([Point(Rect.Left + 6, Rect.Top + 5),
Point(Rect.Left + 6, Rect.Bottom - 5),
Point(Rect.Right - 6, Rect.Top + 8)]);
end
else
if ARow = (Reg.SP shr 1) + 1
then
begin
MemGrid.Canvas.Pen.Color := clGreen;
MemGrid.Canvas.Brush.Color := clGreen;
MemGrid.Canvas.Polygon([Point(Rect.Left + 6, Rect.Top + 5),
Point(Rect.Left + 6, Rect.Bottom - 5),
Point(Rect.Right - 6, Rect.Top + 8)]);
end;
end;
end
else
case ACol of
1: MemGrid.Canvas.TextOut(Rect.Left + 16, Rect.Top + 1, 'Address');
2: MemGrid.Canvas.TextOut(Rect.Left + 10, Rect.Top + 1, 'Lo');
3: MemGrid.Canvas.TextOut(Rect.Left + 10, Rect.Top + 1, 'Hi');
4: MemGrid.Canvas.TextOut(Rect.Left + 10, Rect.Top + 1, 'Word');
end;
end;
procedure TK580MainForm.MemGridGetEditMask(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
if (ACol = 2) or (ACol = 3)
then Value := 'aa;1;0'
else
if ACol = 4
then Value := 'aaaa;1;0';
end;
procedure TK580MainForm.MemGridGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
if ACol = 2
then
Value := IntToHex(Mem[(ARow shl 1) - 2], 2)
else
if ACol = 3
then
Value := IntToHex(Mem[(ARow shl 1) - 1], 2)
else
if ACol = 4
then
Value := IntToHex(((Mem[(ARow shl 1) - 1] shl 8) +
Mem[(ARow shl 1) - 2]), 4);
end;
procedure TK580MainForm.MemGridSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
var
IntVal: Integer;
CanSelect: Boolean;
begin
IntVal := HexToInt(Value);
if ACol = 2
then Mem[(ARow shl 1) - 2] := Byte(IntVal)
else
if ACol = 3
then Mem[(ARow shl 1) - 1] := Byte(IntVal)
else
begin
Mem[(ARow shl 1) - 2] := Byte(IntVal);
Mem[(ARow shl 1) - 1] := Byte(IntVal shr 8);
end;
MemGrid.Repaint;
CanSelect := True;
MemGridSelectCell(Sender, ACol, ARow, CanSelect);
end;
procedure TK580MainForm.MemGridSelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
var
Str: string;
Pos: Word;
begin
if ACol = 4
then Pos := (ARow - 1) shl 1
else Pos := ((ARow - 1) shl 1) + ACol - 2;
GetCmdStr(Mem[Pos], GetNextWordFromMem(Pos), Str);
StatusBar.Panels[1].Text := Str;
end;
procedure TK580MainForm.RegGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
case ACol of
0:
case ARow of
0: RegGrid.Canvas.TextOut(Rect.Left + 6, Rect.Top + 1, 'PSW');
1: RegGrid.Canvas.TextOut(Rect.Left + 10, Rect.Top + 1, 'BC');
2: RegGrid.Canvas.TextOut(Rect.Left + 10, Rect.Top + 1, 'DE');
3: RegGrid.Canvas.TextOut(Rect.Left + 10, Rect.Top + 1, 'HL');
end;
1:
case ARow of
0: RegGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
'A:' + IntToBin(Reg.A));
1: RegGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
'B:' + IntToBin(Reg.B));
2: RegGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
'D:' + IntToBin(Reg.D));
3: RegGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
'H:' + IntToBin(Reg.H));
end;
2:
case ARow of
0: RegGrid.Canvas.TextOut(Rect.Left + 4, Rect.Top + 1,
'F:' + IntToBin(Reg.F));
1: RegGrid.Canvas.TextOut(Rect.Left + 4, Rect.Top + 1,
'C:' + IntToBin(Reg.C));
2: RegGrid.Canvas.TextOut(Rect.Left + 4, Rect.Top + 1,
'E:' + IntToBin(Reg.E));
3: RegGrid.Canvas.TextOut(Rect.Left + 4, Rect.Top + 1,
'L:' + IntToBin(Reg.L));
end;
end;
end;
procedure TK580MainForm.RegGridGetEditMask(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
Value := 'aa;1;0';
end;
procedure TK580MainForm.RegGridGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
case ACol of
1:
case ARow of
0: Value := IntToHex(Reg.A, 2);
1: Value := IntToHex(Reg.B, 2);
2: Value := IntToHex(Reg.D, 2);
3: Value := IntToHex(Reg.H, 2);
end;
2:
case ARow of
0: Value := IntToHex(Reg.F, 2);
1: Value := IntToHex(Reg.C, 2);
2: Value := IntToHex(Reg.E, 2);
3: Value := IntToHex(Reg.L, 2);
end;
end;
end;
procedure TK580MainForm.RegGridSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
begin
case ACol of
1:
case ARow of
0: Reg.A := HexToInt(Value);
1: Reg.B := HexToInt(Value);
2: Reg.D := HexToInt(Value);
3: Reg.H := HexToInt(Value);
end;
2:
case ARow of
0: Reg.F := HexToInt(Value);
1: Reg.C := HexToInt(Value);
2: Reg.E := HexToInt(Value);
3: Reg.L := HexToInt(Value);
end;
end;
RegGrid.Repaint;
end;
procedure TK580MainForm.RegGridSelectSell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
if (ARow = 0) and (ACol = 2)
then CanSelect := False;
end;
procedure TK580MainForm.PCSPGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if ACol = 0
then
if ARow = 0
then PCSPGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1, 'SP')
else PCSPGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1, 'PC')
else
if ARow = 0
then PCSPGrid.Canvas.TextOut(Rect.Left + 1, Rect.Top + 1,
'SP:' + IntToBin(Reg.SP))
else PCSPGrid.Canvas.TextOut(Rect.Left + 1, Rect.Top + 1,
'PC:' + IntToBin(Reg.PC));
end;
procedure TK580MainForm.PCSPGridGetEditMask(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
Value := 'aaaa;1;0'
end;
procedure TK580MainForm.PCSPGridGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
if ARow = 0
then Value := IntToHex(Reg.SP, 4)
else Value := IntToHex(Reg.PC, 4);
end;
procedure TK580MainForm.PCSPGridSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
begin
if ARow = 0
then Reg.SP := HexToInt(Value)
else Reg.PC := HexToInt(Value);
PCSPGrid.Repaint;
MemGrid.Repaint;
end;
procedure TK580MainForm.PortsGridDraw(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if ARow > 0
then
if ACol = 0
then
PortsGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
IntToHex(ARow - 1,2))
else
PortsGrid.Canvas.TextOut(Rect.Left + 8, Rect.Top + 1,
IntToHex(Ports[ARow -1],2))
else
if ACol = 0
then
PortsGrid.Canvas.TextOut(Rect.Left + 6, Rect.Top + 1, 'Num')
else
PortsGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 1,'Port');
end;
procedure TK580MainForm.PortsGridGetEditMask(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
Value := 'aa;1;0';
end;
procedure TK580MainForm.PortsGridGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
if ACol = 1
then
Value := IntToHex(Ports[ARow - 1], 2);
end;
procedure TK580MainForm.PortsGridSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
var
IntVal: Integer;
begin
IntVal := HexToInt(Value);
if ACol = 1
then Ports[ARow - 1] := Byte(IntVal);
PortsGrid.Repaint;
end;
procedure TK580MainForm.LoadMenuClick(Sender: TObject);
begin
if LoadDialog.Execute
then
begin
CodeMemo.Lines.LoadFromFile(LoadDialog.FileName);
K580MainForm.ApplyMenuClick(Sender);
end;
end;
procedure TK580MainForm.ApplyMenuClick(Sender: TObject);
var
Rezult: string;
SntLst: PSentence;
LNLst: TStringList;
Pos: Integer;
CanSelect: Boolean;
begin
SntLst := nil;
Rezult := '';
LNLst := TStringList.Create;
if ReadProgList(CodeMemo.Lines, Rezult, SntLst)
then
if GenerateLNList(SntLst, Rezult, LNLst)
then
if (MemGrid.Row > 0) and (MemGrid.Col > 1)
then
begin
if MemGrid.Col = 4
then Pos := (MemGrid.Row - 1) shl 1
else Pos := ((MemGrid.Row - 1) shl 1) + MemGrid.Col - 2;
Reg.PC := Pos;
Reg.SP := Pos;
WriteProgToMem(SntLst, LNLst, Pos, Mem, Rezult);
end;
MemGrid.Repaint;
PCSPGrid.Repaint;
StatusBar.Panels[0].Text := Rezult;
FreeListObj(LNLst);
LNLst.Free;
DisposeSntList(SntLst);
CanSelect := True;
MemGridSelectCell(Sender, MemGrid.Col, MemGrid.Row, CanSelect);
end;
procedure TK580MainForm.SaveMenuClick(Sender: TObject);
begin
SaveDialog.FilterIndex := 0;
if SaveDialog.Execute
then RezMemo.Lines.SaveToFile(SaveDialog.FileName);
end;
procedure TK580MainForm.HelpMenuClick(Sender: TObject);
begin
Application.HelpCommand(Help_Contents, 0)
end;
procedure TK580MainForm.SaveCodeMenuClick(Sender: TObject);
begin
SaveDialog.FilterIndex := 1;
if SaveDialog.Execute
then CodeMemo.Lines.SaveToFile(SaveDialog.FileName);
end;
procedure TK580MainForm.MainFormCloseClick(Sender: TObject);
begin
K580MainForm.Close;
end;
procedure TK580MainForm.TraceMenuClick(Sender: TObject);
begin
StatusBar.Panels[2].Text := GetRunString;
K580Thread := TK580MP.Create(@Reg, Mem, Ports, @Run, @Int, @CmdInfo,
RegGrid,
PCSPGrid,
MemGrid,
PortsGrid,
StatusBar.Panels[3],
RezMemo.Lines);
K580Thread.OnTerminate := RunThreadTerminate;
end;
procedure TK580MainForm.ExecMenuClick(Sender: TObject);
begin
CodeMemo.Enabled := False;
LoadAction.Enabled := False;
SaveCodeAction.Enabled := False;
SaveAction.Enabled := False;
ApplyAction.Enabled := False;
ClearMemAction.Enabled := False;
TraceAction.Enabled := False;
ExecAction.Enabled := False;
BreakAction.Enabled := True;
Run := True;
StatusBar.Panels[2].Text := GetRunString;
K580Thread := TK580MP.Create(@Reg, Mem, Ports, @Run, @Int, @CmdInfo,
RegGrid,
PCSPGrid,
MemGrid,
PortsGrid,
StatusBar.Panels[3],
RezMemo.Lines);
K580Thread.OnTerminate := RunThreadTerminate;
end;
procedure TK580MainForm.BreakMenuClick(Sender: TObject);
begin
K580Thread.Terminate;
end;
procedure TK580MainForm.RunThreadTerminate(Sender: TObject);
begin
Run := False;
CodeMemo.Enabled := True;
LoadAction.Enabled := True;
SaveCodeAction.Enabled := True;
SaveAction.Enabled := True;
ApplyAction.Enabled := True;
ClearMemAction.Enabled := True;
TraceAction.Enabled := True;
ExecAction.Enabled := True;
BreakAction.Enabled := False;
StatusBar.Panels[2].Text := GetRunString;
MemGrid.Row := (Reg.PC shr 1) + 1;
MemGrid.Col := (Reg.PC and $0001) + 2
end;
procedure TK580MainForm.ClearRezultsMenuClick(Sender: TObject);
begin
RezMemo.Lines.Clear;
RezMemo.Lines.Add(' АДР | МНЕМОНИКА |A B C D E H L |C Z M P A| ПАМЯТЬ |СОДЕРЖАНИЕ');
end;
procedure TK580MainForm.ClearMemMenuClick(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 65535 do
Mem[i] := 0;
CmdInfo.UseMem := False;
CmdInfo.WordMem := False;
MemGrid.Repaint;
end;
end.
Модуль MPUnit разработан Милашовым М. В.
В модуле определен класс TK580MP предназначенный для
программной эмуляции арифметических команд микропроцессорра КР580ВМ60.
MPUnit.pas
unit MPUnit;
{
Модуль MPUnit разработан Милашовым М. В.
В модуле определен класс TK580MP предназначенный для
программной эмуляции арифметических команд микропроцессорра КР580ВМ60.
}
interface
uses SysUtils, Classes, Controls, ComCtrls, AsmUnit;
type
{Регистры микропроцессора.}
TK580Regs = record
PC: Word;
SP: Word;
case Integer of
0: (F, A, C, B, E, D, L, H: Byte);
1: (PSW, BC, DE, HL: Word);
end;
PK580Regs = ^TK580Regs;
{Информация о последней выполненной команде.}
TCmdInfo = record
LastAddr: Word;//Адрес последней выполненной команды.
LastCmd: Byte;//Код последней выполненной команды.
LastTag: Word;//2-й и 3-й байты последней выполненной команды.
UseMem: Boolean;//Признак обращения к памяти.
WordMem: Boolean;//Признак обращения к слову в памяти.
MemAddr: Word;//Адрес ячейки памяти.
MemValue: Word;//Содержимое ячейки памяти после выполнения команды.
Contents: string;//Информация о команде.
end;
PCmdInfo = ^TCmdInfo;
BBoolean = ^Boolean;
{Класс "Микропроцессор К580".}
TK580MP = class(TThread)
protected
Reg: PK580Regs;//Регистры микропроцессора.
Mem: PByteList;//Память.
Ports: PByteList;//Порты ввода-вывода.
Run: PBoolean;//Флаг запуска программы.
Int: PBoolean;//Флаг запрета/разрешения прерывания.
CmdInfo: PCmdInfo;//Информация о последней выполненной команде
RegGrid: TWinControl;
PCSPGrid: TWinControl;
MemGrid: TWinControl;
PortsGrid: TWinControl;
IntStatus: TStatusPanel;
RezStrings: TStrings;
function GetCY: Byte;
function GetZ: Byte;
function GetM: Byte;
function GetP: Byte;
procedure SetZMP(Rez: Byte);//Установка флагов Z, M и P по результату операции.
procedure SetCY(Op1: Byte; Op2: Byte); overload;//Установка флага CY по
procedure SetCY(Op1: Word; Op2: Word); overload;//передаваемым операндам.
procedure SetCY(Op1: Byte; Op2: Byte; Op3: Byte); overload;
procedure SetAC(Op1: Byte; Op2: Byte); overload;//Установка флага AC.
procedure SetAC(Op1: Byte; Op2: Byte; Op3: Byte); overload;
function GetSSS(Code: Byte): Byte;//Получить содержимое регистра источника по коду команды.
function GetDDD(Code: Byte): Byte;//ПолучитьСодержимое регистра приемника.
procedure SetDDD(Code: Byte; Data: Byte);//Записать данные в регистр приемник.
function GetDataPort: Byte;//Получить 8-ми разрядный литерал или адрес порта.
function GetData16Addr: Word;//Получить 16-ти разрядный литерал или адрес памяти.
function GetWordFromMem(Addr: Word): Word;//Получить слово из памяти.
procedure SetWordToMem(Addr: Word; Data: Word);//Записать слово в память.
function GetRun: Boolean;
procedure SetRun(RunStop: Boolean);
function GetInt: Boolean;
procedure SetInt(IntNotInt: Boolean);
function GetIntString: string;
function GetRezString: string;//Получить строку с информацией о последней выполненной команде.
procedure JMP(Addr: Word);
procedure CALL(Addr: Word);
procedure RET;
procedure DefaultTrace;//Начальная установка информации о последней выполненной команде.
procedure ExchangeTrace;//Выполнение команд обмена данными между памятью и регистрами.
procedure LogicTrace;//Выполнение логических команд.
procedure ArifhmTrace;//Выполнение арифметических команд.
procedure JmpTrace;//Выполнение команд перехода.
procedure MPTrace;//Выполнение команд микропроцессора.
procedure TraceProg; overload;//Трассировка (можно переопределить в классах потомках).
procedure RunProg; overload;//Выполнение (можно переопределить в классах потомках).
procedure Execute; override;
{ Protected declarations }
public
constructor Create(PReg: PK580Regs;
PMem: PByteList;
PPorts: PByteList;
PRun: PBoolean;
PInt: PBoolean;
PCmdInf: PCmdInfo;
PRegGrid: TWinControl;
PPCSPGrid: TWinControl;
PMemGrid: TWinControl;
PPortsGrid: TWinControl;
PIntStatus: TStatusPanel;
PRezStrings: TStrings);
{ Public declarations }
end;
implementation
constructor TK580MP.Create(PReg: PK580Regs;
PMem: PByteList;
PPorts: PByteList;
PRun: PBoolean;
PInt: PBoolean;
PCmdInf: PCmdInfo;
PRegGrid: TWinControl;
PPCSPGrid: TWinControl;
PMemGrid: TWinControl;
PPortsGrid: TWinControl;
PIntStatus: TStatusPanel;
PRezStrings: TStrings);
begin
inherited Create(False);
Reg := PReg;
Mem := PMem;
Ports := PPorts;
Run := PRun;
Int := PInt;
CmdInfo := PCmdInf;
RegGrid := PRegGrid;
PCSPGrid := PPCSPGrid;
MemGrid := PMemGrid;
PortsGrid := PPortsGrid;
IntStatus := PIntStatus;
RezStrings := PRezStrings;
FreeOnTerminate := True;
end;
procedure TK580MP.Execute;
begin
while not Terminated do
Synchronize(RunProg);
end;
function TK580MP.GetCY: Byte;
begin
GetCY := Reg^.F and $01;
end;
function TK580MP.GetZ: Byte;
begin
GetZ := (Reg^.F and $40) shr 6;
end;
function TK580MP.GetM: Byte;
begin
GetM := (Reg^.F and $80) shr 7;
end;
function TK580MP.GetP: Byte;
begin
GetP := (Reg^.F and $04) shr 2;
end;
procedure TK580MP.SetZMP(Rez: Byte);
var
P: Byte;
begin
if Rez = 0
then Reg^.F := Reg^.F or $40
else Reg^.F := Reg^.F and $BF;
if (Rez and $80) = 0
then Reg^.F := Reg^.F and $7F
else Reg^.F := Reg^.F or $80;
P := 0;
while Rez <> 0 do
begin
P := P xor (Rez and $01);
Rez := Rez shr 1;
end;
if P = 0
then Reg^.F := Reg^.F or $04
else Reg^.F := Reg^.F and $FB;
end;
procedure TK580MP.SetCY(Op1: Byte; Op2: Byte);
begin
if ((Op1 + Op2) and $0100) <> 0
then Reg^.F := Reg^.F or $01
else Reg^.F := Reg^.F and $FE;
end;
procedure TK580MP.SetCY(Op1: Word; Op2: Word);
begin
if ((Op1 + Op2) and $010000) <> 0
then Reg^.F := Reg^.F or $01
else Reg^.F := Reg^.F and $FE;
end;
procedure TK580MP.SetCY(Op1: Byte; Op2: Byte; Op3: Byte);
begin
if ((Op1 + Op2 + Op3) and $0100) <> 0
then Reg^.F := Reg^.F or $01
else Reg^.F := Reg^.F and $FE;
end;
procedure TK580MP.SetAC(Op1: Byte; Op2: Byte);
begin
if (((Op1 and $0F) + (Op2 and $0F)) and $10) <> 0
then Reg^.F := Reg^.F or $10
else Reg^.F := Reg^.F and $EF;
end;
procedure TK580MP.SetAC(Op1: Byte; Op2: Byte; Op3: Byte);
begin
if (((Op1 and $0F) + (Op2 and $0F) + (Op3 and $0F)) and $10) <> 0
then Reg^.F := Reg^.F or $10
else Reg^.F := Reg^.F and $EF;
end;
function TK580MP.GetSSS(Code: Byte): Byte;
var
SSS: Byte;
begin
SSS := Code and $07;
case SSS of
0: GetSSS := Reg^.B;
1: GetSSS := Reg^.C;
2: GetSSS := Reg^.D;
3: GetSSS := Reg^.E;
4: GetSSS := Reg^.H;
5: GetSSS := Reg^.L;
else GetSSS := Reg^.A;
end;
end;
function TK580MP.GetDDD(Code: Byte): Byte;
var
DDD: Byte;
begin
DDD := (Code and $38) shr 3;
GetDDD := GetSSS(DDD);
end;
procedure TK580MP.SetDDD(Code: Byte; Data: Byte);
var
DDD: Byte;
begin
DDD := (Code and $38) shr 3;
case DDD of
0: Reg^.B := Data;
1: Reg^.C := Data;
2: Reg^.D := Data;
3: Reg^.E := Data;
4: Reg^.H := Data;
5: Reg^.L := Data;
6: ;
else Reg^.A := Data;
end;
end;
function TK580MP.GetDataPort: Byte;
begin
if Reg^.PC < 65535
then
GetDataPort := Mem[Reg^.PC + 1]
else
GetDataPort := Mem[0];
end;
function TK580MP.GetData16Addr: Word;
begin
if Reg^.PC < 65534
then
GetData16Addr := (Mem[Reg^.PC + 2] shl 8) + Mem[Reg^.PC + 1]
else
if Reg^.PC < 65535
then
GetData16Addr := (Mem[0] shl 8) + Mem[Reg^.PC + 1]
else
GetData16Addr := (Mem[1] shl 8) + Mem[0];
end;
function TK580MP.GetWordFromMem(Addr: Word): Word;
begin
if Addr < 65535
then
GetWordFromMem := (Mem[Addr + 1] shl 8) + Mem[Addr]
else
GetWordFromMem := (Mem[0] shl 8) + Mem[Addr];
end;
procedure TK580MP.SetWordToMem(Addr: Word; Data: Word);
begin
if Addr < 65535
then
begin
Mem[Addr + 1] := (Data and $FF00) shr 8;
Mem[Addr] := Data and $FF;
end
else
begin
Mem[0] := (Data and $FF00) shr 8;
Mem[Addr] := Data and $FF;
end;
end;
function TK580MP.GetRun: Boolean;
begin
GetRun := Run^;
end;
procedure TK580MP.SetRun(RunStop: Boolean);
begin
Run^ := RunStop;
end;
function TK580MP.GetInt: Boolean;
begin
GetInt := Int^;
end;
procedure TK580MP.SetInt(IntNotInt: Boolean);
begin
Int^ := IntNotInt;
end;
function TK580MP.GetIntString: string;
begin
if GetInt
then GetIntString := 'Yes'
else GetIntString := 'No';
end;
function TK580MP.GetRezString: string;
var
Str, TmpStr: string;
begin
Str := IntToHex(CmdInfo^.LastAddr, 4) + ': ';
GetCmdStr(CmdInfo^.LastCmd, CmdInfo^.LastTag, TmpStr);
while Length(TmpStr) < 12 do
TmpStr := TmpStr + ' ';
Str := Str + TmpStr + ' ' + IntToHex(Reg^.A, 2) +
' ' + IntToHex(Reg^.B, 2) + ' ' + IntToHex(Reg^.C, 2) +
' ' + IntToHex(Reg^.D, 2) + ' ' + IntToHex(Reg^.E, 2) +
' ' + IntToHex(Reg^.H, 2) + ' ' + IntToHex(Reg^.L, 2) + ' ';
TmpStr := '0 0 0 0 0 ';
if (Reg^.F and $01) = $01
then TmpStr[1] := '1';
if (Reg^.F and $40) = $40
then TmpStr[3] := '1';
if (Reg^.F and $80) = $80
then TmpStr[5] := '1';
if (Reg^.F and $04) = $04
then TmpStr[7] := '1';
if (Reg^.F and $10) = $10
then TmpStr[9] := '1';
Str := Str + TmpStr;
if CmdInfo^.UseMem
then
begin
TmpStr := '(' + IntToHex(CmdInfo^.MemAddr, 4) + ')';
if CmdInfo^.WordMem
then TmpStr := TmpStr + IntToHex(CmdInfo^.MemValue, 4)
else TmpStr := TmpStr + IntToHex(CmdInfo^.MemValue, 2) + ' ';
end
else TmpStr := ' ';
Str := Str + TmpStr + ' ' + CmdInfo^.Contents;
GetRezString := Str;
end;
procedure TK580MP.DefaultTrace;
begin
CmdInfo^.LastAddr := Reg^.PC;
CmdInfo^.LastCmd := Mem[Reg^.PC];
CmdInfo^.LastTag := GetData16Addr;
CmdInfo^.UseMem := False;
CmdInfo^.WordMem := False;
CmdInfo^.Contents := '';
end;
procedure TK580MP.ExchangeTrace;
var
Addr, Data: Word;
S: Byte;
begin
case Mem[Reg^.PC] of
$40..$45, $47..$4D, $4F..$55, $57..$5D, $5F..$65, $67..$6D, $6F, $78..$7D, $7F:
begin
S := GetSSS(Mem[Reg^.PC]);
SetDDD(Mem[Reg^.PC],S);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'dst <- src';
end;
$46, $4E, $56, $5E, $66, $6E, $7E:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
SetDDD(Mem[Reg^.PC],Mem[Reg^.HL]);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'dst <- (HL)';
end;
$70..$75, $77:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
Mem[Reg^.HL] := GetSSS(Mem[Reg^.PC]);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '(HL) <- src';
end;
$06, $0E, $16, $1E, $26, $2E, $3E:
begin
SetDDD(Mem[Reg^.PC],GetDataPort);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'dst <- data';
end;
$36:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
Mem[Reg^.HL] := GetDataPort;
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := '(HL) <- data';
end;
$3A:
begin
Addr := GetData16Addr;
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Addr;
Reg^.A := Mem[Addr];
CmdInfo^.MemValue := Mem[Addr];
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'A <- (addr)';
end;
$32:
begin
Addr := GetData16Addr;
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Addr;
Mem[Addr] := Reg^.A;
CmdInfo^.MemValue := Mem[Addr];
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := '(addr) <- A';
end;
$0A:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.BC;
Reg^.A := Mem[Reg^.BC];
CmdInfo^.MemValue := Mem[Reg^.BC];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- (BC)';
end;
$1A:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.DE;
Reg^.A := Mem[Reg^.DE];
CmdInfo^.MemValue := Mem[Reg^.DE];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- (DE)';
end;
$02:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.BC;
Mem[Reg^.BC] := Reg^.A;
CmdInfo^.MemValue := Mem[Reg^.BC];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '(BC) <- A';
end;
$12:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.DE;
Mem[Reg^.DE] := Reg^.A;
CmdInfo^.MemValue := Mem[Reg^.DE];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '(DE) <- A';
end;
$01:
begin
Reg^.BC := GetData16Addr;
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'BC <- data16';
end;
$11:
begin
Reg^.DE := GetData16Addr;
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'DE <- data16';
end;
$21:
begin
Reg^.HL := GetData16Addr;
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'HL <- data16';
end;
$31:
begin
Reg^.SP := GetData16Addr;
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'SP <- data16';
end;
$2A:
begin
Addr := GetData16Addr;
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Addr;
Data := GetWordFromMem(Addr);
Reg^.HL := Data;
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'HL <- (addr)';
end;
$22:
begin
Addr := GetData16Addr;
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Addr;
Data := Reg^.HL;
SetWordToMem(Addr, Data);
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'HL <- (addr)';
end;
$F9:
begin
Reg^.SP := Reg^.HL;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'SP <- HL';
end;
$C5:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
Reg^.SP := Reg^.SP - 2;
CmdInfo^.MemAddr := Reg^.SP;
Data := Reg^.BC;
SetWordToMem(Reg^.SP, Data);
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '-(SP) <- BC';
end;
$D5:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
Reg^.SP := Reg^.SP - 2;
CmdInfo^.MemAddr := Reg^.SP;
Data := Reg^.DE;
SetWordToMem(Reg^.SP, Data);
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '-(SP) <- DE';
end;
$E5:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
Reg^.SP := Reg^.SP - 2;
CmdInfo^.MemAddr := Reg^.SP;
Data := Reg^.HL;
SetWordToMem(Reg^.SP, Data);
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '-(SP) <- HL';
end;
$F5:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
Reg^.SP := Reg^.SP - 2;
CmdInfo^.MemAddr := Reg^.SP;
Data := Reg^.PSW;
SetWordToMem(Reg^.SP, Data);
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '-(SP) <- PSW';
end;
$C1:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Reg^.SP;
Data := GetWordFromMem(Reg^.SP);
Reg^.BC := Data;
Reg^.SP := Reg^.SP + 2;
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'BC <- (SP)+';
end;
$D1:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Reg^.SP;
Data := GetWordFromMem(Reg^.SP);
Reg^.DE := Data;
Reg^.SP := Reg^.SP + 2;
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'DE <- (SP)+';
end;
$E1:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Reg^.SP;
Data := GetWordFromMem(Reg^.SP);
Reg^.HL := Data;
Reg^.SP := Reg^.SP + 2;
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- (SP)+';
end;
$F1:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Reg^.SP;
Data := GetWordFromMem(Reg^.SP);
Reg^.PSW := Data;
Reg^.SP := Reg^.SP + 2;
CmdInfo^.MemValue := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'PSW <- (SP)+';
end;
$EB:
begin
Data := Reg^.DE;
Reg^.DE := Reg^.HL;
Reg^.HL := Data;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'DE <-> HL';
end;
$E3:
begin
CmdInfo^.UseMem := True;
CmdInfo^.WordMem := True;
CmdInfo^.MemAddr := Reg^.SP;
Data := GetWordFromMem(Reg^.SP);
SetWordToMem(Reg^.SP,Reg^.HL);
Reg^.HL := Data;
CmdInfo^.MemValue := Reg^.HL;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '(SP) <-> HL';
end;
end;
end;
procedure TK580MP.LogicTrace;
var
S, Data: Byte;
CY: Word;
begin
case Mem[Reg^.PC] of
$A0..$A5, $A7:
begin
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
S := GetSSS(Mem[Reg^.PC]);
Reg^.A := Reg^.A and S;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A AND src';
end;
$A8..$AD, $AF:
begin
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
S := GetSSS(Mem[Reg^.PC]);
Reg^.A := Reg^.A xor S;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A XOR src';
end;
$B0..$B5, $B7:
begin
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
S := GetSSS(Mem[Reg^.PC]);
Reg^.A := Reg^.A or S;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A OR src';
end;
$B8..$BD, $BF:
begin
S := GetSSS(Mem[Reg^.PC]);
SetCY(Reg^.A, Byte(-S));
SetAC(Reg^.A, Byte(-S));
SetZMP(Reg^.A - S);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A-src';
end;
$A6:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
Reg^.A := Reg^.A and Mem[Reg^.HL];
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A AND (HL)';
end;
$AE:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
Reg^.A := Reg^.A xor Mem[Reg^.HL];
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A XOR (HL)';
end;
$B6:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
Reg^.A := Reg^.A or Mem[Reg^.HL];
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A OR (HL)';
end;
$BE:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
SetCY(Reg^.A, Byte(-Mem[Reg^.HL]));
SetAC(Reg^.A, Byte(-Mem[Reg^.HL]));
SetZMP(Reg^.A - Mem[Reg^.HL]);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A-(HL)';
end;
$E6:
begin
Data := GetDataPort;
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
Reg^.A := Reg^.A and Data;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A AND data';
end;
$EE:
begin
Data := GetDataPort;
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
Reg^.A := Reg^.A xor Data;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A XOR data';
end;
$F6:
begin
Data := GetDataPort;
Reg^.F := Reg^.F and $FE;
Reg^.F := Reg^.F and $EF;
Reg^.A := Reg^.A or Data;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A OR data';
end;
$FE:
begin
Data := GetDataPort;
SetCY(Reg^.A, Byte(-Data));
SetAC(Reg^.A, Byte(-Data));
SetZMP(Reg^.A - Data);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A-data';
end;
$07:
begin
if (Reg^.A and $80) <> 0 then
begin
Reg^.F := Reg^.F or $01;
Reg^.A := ((Reg^.A shl 1) and $FE) + 1;
end
else
begin
Reg^.F := Reg^.F and $FE;
Reg^.A := ((Reg^.A shl 1) and $FE);
end;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A7 <- A6 <- ... <- A0 <- A7';
end;
$0F:
begin
if (Reg^.A and $01) <> 0 then
begin
Reg^.F := Reg^.F or $01;
Reg^.A := ((Reg^.A shr 1) and $7F) + $80;
end
else
begin
Reg^.F := Reg^.F and $FE;
Reg^.A := ((Reg^.A shr 1) and $7F);
end;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A0 <- A1 <- ... <- A7 <- A0';
end;
$17:
begin
CY := GetCY;
if (Reg^.A and $80) <> 0 then
begin
Reg^.F := Reg^.F or $01;
Reg^.A := ((Reg^.A shl 1) and $FE) + CY;
end
else
begin
Reg^.F := Reg^.F and $FE;
Reg^.A := ((Reg^.A shl 1) and $FE) + CY;
end;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A7 <- A6 <- ... <- A0 <- CY <- A7';
end;
$1F:
begin
CY := GetCY shl 7;
if (Reg^.A and $01) <> 0 then
begin
Reg^.F := Reg^.F or $01;
Reg^.A := ((Reg^.A shr 1) and $7F) + CY;
end
else
begin
Reg^.F := Reg^.F and $FE;
Reg^.A := ((Reg^.A shr 1) and $7F) + CY;
end;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A0 <- A1 <- ... <- A7 <- CY <- A0';
end;
$2E:
begin
Reg^.A := not Reg^.A;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- NOT A';
end;
$3F:
begin
if (Reg^.F and $01) <> 0
then
Reg^.F := Reg^.F and $FE
else
Reg^.F := Reg^.F or $01;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'CY <- NOT CY';
end;
$37:
begin
Reg^.F := Reg^.F or $01;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'CY <- 1';
end;
end;
end;
procedure TK580MP.ArifhmTrace;
var
S, CY, Data: Byte;
begin
case Mem[Reg^.PC] of
$80..$85, $87:
begin
S := GetSSS(Mem[Reg^.PC]);
SetCY(Reg^.A, S);
SetAC(Reg^.A, S);
Reg^.A := Reg^.A + S;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A + src';
end;
$88..$8D, $8F:
begin
S := GetSSS(Mem[Reg^.PC]);
CY := Reg^.F and $01;
SetCY(Reg^.A, S, CY);
SetAC(Reg^.A, S, CY);
Reg^.A := Reg^.A + S + CY;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A + src + CY';
end;
$90..$95, $97:
begin
S := GetSSS(Mem[Reg^.PC]);
SetCY(Reg^.A, Byte(-S));
SetAC(Reg^.A, Byte(-S));
Reg^.A := Reg^.A - S;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A - src';
end;
$98..$9D, $9F:
begin
S := GetSSS(Mem[Reg^.PC]);
CY := GetCY;
SetCY(Reg^.A, Byte(-S), Byte(-CY));
SetAC(Reg^.A, Byte(-S), Byte(-CY));
Reg^.A := Reg^.A - S - CY;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A - src - CY';
end;
$86:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
SetCY(Reg^.A, Mem[Reg^.HL]);
SetAC(Reg^.A, Mem[Reg^.HL]);
Reg^.A := Reg^.A + Mem[Reg^.HL];
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A + (HL)';
end;
$8E:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
CY := GetCY;
SetCY(Reg^.A, Mem[Reg^.HL], CY);
SetAC(Reg^.A, Mem[Reg^.HL], CY);
Reg^.A := Reg^.A + Mem[Reg^.HL] + CY;
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A + (HL) + CY';
end;
$96:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
SetCY(Reg^.A, Byte(-Mem[Reg^.HL]));
SetAC(Reg^.A, Byte(-Mem[Reg^.HL]));
Reg^.A := Reg^.A - Mem[Reg^.HL];
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A - (HL)';
end;
$9E:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
CY := GetCY;
SetCY(Reg^.A, Byte(-Mem[Reg^.HL]), Byte(-CY));
SetAC(Reg^.A, Byte(-Mem[Reg^.HL]), Byte(-CY));
Reg^.A := Reg^.A - Mem[Reg^.HL] - CY;
SetZMP(Reg^.A);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- A - (HL) - CY';
end;
$C6:
begin
Data := GetDataPort;
SetCY(Reg^.A, Data);
SetAC(Reg^.A, Data);
Reg^.A := Reg^.A + Data;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A + data';
end;
$CE:
begin
CY := GetCY;
Data := GetDataPort;
SetCY(Reg^.A, Data, CY);
SetAC(Reg^.A, Data, CY);
Reg^.A := Reg^.A + Data + CY;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A + data + CY';
end;
$D6:
begin
Data := GetDataPort;
SetCY(Reg^.A, Byte(-Data));
SetAC(Reg^.A, Byte(-Data));
Reg^.A := Reg^.A - Data;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A - data';
end;
$DE:
begin
Data := GetDataPort;
CY := GetCY;
SetCY(Reg^.A, Byte(-Data), Byte(-CY));
SetAC(Reg^.A, Byte(-Data), Byte(-CY));
Reg^.A := Reg^.A - Data - CY;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- A - data - CY';
end;
$04, $0C, $14, $1C, $24, $2C, $3C:
begin
S := GetDDD(Mem[Reg^.PC]);
SetAC(S, 1);
S := S + 1;
SetDDD(Mem[Reg^.PC],S);
SetZMP(S);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'dst <- dst + 1';
end;
$05, $0D, $15, $1D, $25, $2D, $3D:
begin
S := GetDDD(Mem[Reg^.PC]);
SetAC(S, Byte(-1));
S := S - 1;
SetDDD(Mem[Reg^.PC],S);
SetZMP(S);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'dst <- dst - 1';
end;
$34:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
SetAC(Mem[Reg^.HL], 1);
Mem[Reg^.HL] := Mem[Reg^.HL] + 1;
SetZMP(Mem[Reg^.HL]);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '(HL) <- (HL) + 1';
end;
$35:
begin
CmdInfo^.UseMem := True;
CmdInfo^.MemAddr := Reg^.HL;
SetAC(Mem[Reg^.HL], Byte(-1));
Mem[Reg^.HL] := Mem[Reg^.HL] - 1;
SetZMP(Mem[Reg^.HL]);
CmdInfo^.MemValue := Mem[Reg^.HL];
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := '(HL) <- (HL) - 1';
end;
$27:
begin
if (Reg^.A and $0F) > $09
then
begin
Reg^.F := Reg^.F or $10;
Reg^.A := Reg^.A + $06;
end
else Reg^.F := Reg^.F and $EF;
if (Reg^.A and $F0) > $90
then
begin
Reg^.F := Reg^.F or $01;
Reg^.A := Reg^.A + $60;
end
else Reg^.F := Reg^.F and $FE;
SetZMP(Reg^.A);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'A <- 2/10 коррекция A';
end;
$09:
begin
SetCY(Reg^.HL, Reg^.BC);
Reg^.HL := Reg^.HL + Reg^.BC;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- HL + BC';
end;
$19:
begin
SetCY(Reg^.HL, Reg^.DE);
Reg^.HL := Reg^.HL + Reg^.DE;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- HL + DE';
end;
$29:
begin
SetCY(Reg^.HL, Reg^.HL);
Reg^.HL := Reg^.HL + Reg^.HL;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- HL + HL';
end;
$39:
begin
SetCY(Reg^.HL, Reg^.SP);
Reg^.HL := Reg^.HL + Reg^.SP;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- HL + SP';
end;
$03:
begin
Reg^.BC := Reg^.BC + 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'BC <- BC + 1';
end;
$13:
begin
Reg^.DE := Reg^.DE + 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'DE <- DE + 1';
end;
$23:
begin
Reg^.HL := Reg^.HL + 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- HL + 1';
end;
$33:
begin
Reg^.SP := Reg^.SP + 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'SP <- SP + 1';
end;
$0B:
begin
Reg^.BC := Reg^.BC - 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'BC <- BC - 1';
end;
$1B:
begin
Reg^.DE := Reg^.DE - 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'DE <- DE - 1';
end;
$2B:
begin
Reg^.HL := Reg^.HL - 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'HL <- HL - 1';
end;
$3B:
begin
Reg^.SP := Reg^.SP - 1;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'SP <- SP - 1';
end;
end;
end;
procedure TK580MP.JMP(Addr: Word);
begin
Reg^.PC := Addr;
end;
procedure TK580MP.CALL(Addr: Word);
begin
Reg^.SP := Reg^.SP - 2;
SetWordToMem(Reg^.SP, Word(Reg^.PC + 3));
Reg^.PC := Addr;
end;
procedure TK580MP.RET;
begin
Reg^.PC := GetWordFromMem(Reg^.SP);
Reg^.SP := Reg^.SP + 2
end;
procedure TK580MP.JmpTrace;
begin
case Mem[Reg^.PC] of
$E9:
begin
Reg^.PC := Reg^.HL;
CmdInfo^.Contents := 'PC <- HL';
end;
$C3:
begin
JMP(GetData16Addr);
CmdInfo^.Contents := 'PC <- addr';
end;
$DA:
begin
if GetCY = 1
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если CY = 1, то JMP addr';
end;
$D2:
begin
if GetCY = 0
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если CY = 0, то JMP addr';
end;
$CA:
begin
if GetZ = 1
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если Z = 1, то JMP addr';
end;
$C2:
begin
if GetZ = 0
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если Z = 0, то JMP addr';
end;
$FA:
begin
if GetM = 1
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если M = 1, то JMP addr';
end;
$F2:
begin
if GetM = 0
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если M = 0, то JMP addr';
end;
$EA:
begin
if GetP = 1
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если P = 1, то JMP addr';
end;
$E2:
begin
if GetP = 0
then JMP(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если P = 0, то JMP addr';
end;
$CD:
begin
CALL(GetData16Addr);
CmdInfo^.Contents := '-(SP) <- PC <- addr';
end;
$DC:
begin
if GetCY = 1
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если CY = 1, то CALL addr';
end;
$D4:
begin
if GetCY = 0
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если CY = 0, то CALL addr';
end;
$CC:
begin
if GetZ = 1
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если Z = 1, то CALL addr';
end;
$C4:
begin
if GetZ = 0
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если Z = 0, то CALL addr';
end;
$FC:
begin
if GetM = 1
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если M = 1, то CALL addr';
end;
$F4:
begin
if GetM = 0
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если M = 0, то CALL addr';
end;
$EC:
begin
if GetP = 1
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если P = 1, то CALL addr';
end;
$E4:
begin
if GetP = 0
then CALL(GetData16Addr)
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если P = 0, то CALL addr';
end;
$C9:
begin
RET;
CmdInfo^.Contents := 'PC <- (SP)+';
end;
$D8:
begin
if GetCY = 1
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если CY = 1, то RET addr';
end;
$D0:
begin
if GetCY = 0
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если CY = 0, то RET addr';
end;
$C8:
begin
if GetZ = 1
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если Z = 1, то RET addr';
end;
$C0:
begin
if GetZ = 0
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если Z = 0, то RET addr';
end;
$F8:
begin
if GetM = 1
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если M = 1, то CALL addr';
end;
$F0:
begin
if GetM = 0
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если M = 0, то RET addr';
end;
$E8:
begin
if GetP = 1
then RET
else Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Если P = 1, то RET addr';
end;
$E0:
begin
if GetP = 0
then RET
else Reg^.PC := Reg^.PC + 3;
CmdInfo^.Contents := 'Если P = 0, то RET addr';
end;
end;
end;
procedure TK580MP.MPTrace;
var
NNN: Byte;
begin
case Mem[Reg^.PC] of
$DB:
begin
Reg^.A := Ports[GetDataPort];
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'A <- IOSEG(port)';
end;
$D3:
begin
Ports[GetDataPort] := Reg^.A;
Reg^.PC := Reg^.PC + 2;
CmdInfo^.Contents := 'IOSEG(port) <- A';
end;
$C7, $CF, $D7, $DF, $E7, $EF, $F7, $FF:
begin
if GetInt
then
begin
NNN := (Mem[Reg^.PC] and $38) shr 3;
Reg^.SP := Reg^.SP - 1;
Mem[Reg^.SP] := Reg^.PC;
Reg^.PC := 8 * NNN;
CmdInfo^.Contents := '-(SP) <- PC <- 8*n';
end
else
begin
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Прерывания запрещены';
end;
end;
$FB:
begin
Int^ := True;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Разрешение прерываний';
end;
$F3:
begin
Int^ := False;
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Запрет прерываний';
end;
$76:
begin
SetRun(False);
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Останов';
end;
$00:
begin
Reg^.PC := Reg^.PC + 1;
CmdInfo^.Contents := 'Нет операции';
end;
end;
end;
procedure TK580MP.TraceProg;
begin
DefaultTrace;
case Mem[Reg^.PC] of
$40..$75, $77..$7F,
$06, $0E, $16, $1E, $26, $2E, $3E,
$36, $3A, $32, $0A, $1A, $02, $12, $01, $21, $31, $2A, $22, $F9,
$C5, $D5, $E5, $F5, $C1, $D1, $E1, $F1, $EB, $E3:
ExchangeTrace;
$A0..$BF,
$E6, $EE, $F6, $FE, $07, $0F, $17, $1F, $2F, $3F, $37:
LogicTrace;
$80..$9F,
$C6, $CE, $D6, $DE,
$04, $0C, $14, $1C, $24, $2C, $3C, $05, $0D, $15, $1D, $25, $2D, $3D,
$34, $35, $27, $09, $19, $29, $39, $03, $13, $23, $33, $0B, $1B, $2B, $3B:
ArifhmTrace;
$E9, $C3, $DA, $D2, $CA, $C2, $FA, $F2, $EA, $E2,
$CD, $DC, $D4, $CC, $C4, $FC, $F4, $EC, $E4, $C9,
$D8, $D0, $C8, $C0, $F8, $F0, $E8, $E0:
JmpTrace;
$DB, $D3, $FB, $F3, $76, $00,
$C7, $CF, $D7, $DF, $E7, $EF, $F7, $FF:
MPTrace;
end;
RegGrid.Repaint;
PCSPGrid.Repaint;
MemGrid.Repaint;
PortsGrid.Repaint;
IntStatus.Text := GetIntString;
RezStrings.Add(GetRezString);
Terminate;
end;
procedure TK580MP.RunProg;
begin
DefaultTrace;
case Mem[Reg^.PC] of
$40..$75, $77..$7F,
$06, $0E, $16, $1E, $26, $2E, $3E,
$36, $3A, $32, $0A, $1A, $02, $12, $01, $21, $31, $2A, $22, $F9,
$C5, $D5, $E5, $F5, $C1, $D1, $E1, $F1, $EB, $E3:
ExchangeTrace;
$A0..$BF,
$E6, $EE, $F6, $FE, $07, $0F, $17, $1F, $2F, $3F, $37:
LogicTrace;
$80..$9F,
$C6, $CE, $D6, $DE,
$04, $0C, $14, $1C, $24, $2C, $3C, $05, $0D, $15, $1D, $25, $2D, $3D,
$34, $35, $27, $09, $19, $29, $39, $03, $13, $23, $33, $0B, $1B, $2B, $3B:
ArifhmTrace;
$E9, $C3, $DA, $D2, $CA, $C2, $FA, $F2, $EA, $E2,
$CD, $DC, $D4, $CC, $C4, $FC, $F4, $EC, $E4, $C9,
$D8, $D0, $C8, $C0, $F8, $F0, $E8, $E0:
JmpTrace;
$DB, $D3, $FB, $F3, $76, $00,
$C7, $CF, $D7, $DF, $E7, $EF, $F7, $FF:
MPTrace;
end;
RegGrid.Repaint;
PCSPGrid.Repaint;
MemGrid.Repaint;
PortsGrid.Repaint;
IntStatus.Text := GetIntString;
RezStrings.Add(GetRezString);
if not GetRun
then Terminate;
end;
end.
ThrdUnit.pas
unit ThrdUnit;
interface
uses Classes, Controls, ComCtrls, AsmUnit, MPUnit;
type
TMPThread = class(TThread)
private
// RegGrid: TWinControl;
// PCSPGrid: TWinControl;
// MemGrid: TWinControl;
// PortsGrid: TWinControl;
// RunStatus: TStatusPanel;
// IntStatus: TStatusPanel;
// RezMemo: TMemo;
// Trace: Boolean;
{ Private declarations }
protected
MicroProc: TK580MP;
procedure DoWork;
procedure Execute; override;
{ Protected declarations }
public
constructor Create(PReg: PK580Regs; PMem: PByteList; PPorts: PByteList;
PRun: PBoolean; PInt: PBoolean; PComandInfo: PCmdInfo);
// PRegGrid: TWinControl; PPCSPGrid: TWinControl;
// PMemGrid: TWinControl; PPortsGrid: TWinControl;
// PRunStatus: TStatusPanel; PIntStatus: TStatusPanel;
// PRezStrings: TStrings; TraceRun: Boolean);
{ Public declarations }
end;
implementation
constructor TMPThread.Create(PReg: PK580Regs; PMem: PByteList; PPorts: PByteList;
PRun: PBoolean; PInt: PBoolean; PComandInfo: PCmdInfo);
// PRegGrid: TWinControl; PPCSPGrid: TWinControl;
// PMemGrid: TWinControl; PPortsGrid: TWinControl;
// PRunStatus: TStatusPanel; PIntStatus: TStatusPanel;
// PRezMemo: TMemo; TraceRun: Boolean);
begin
inherited Create(False);
MicroProc.Create(PReg, PMem, PPorts, PRun, PInt, PComandInfo);
// RegGrid := PRegGrid;
// PCSPGrid := PPCSPGrid;
// MemGrid := PMemGrid;
// PortsGrid := PPortsGrid;
// RunStatus := PRunStatus;
// IntStatus := PIntStatus;
// RezMemo := PRezMemo;
// Trace := TraceRun;
FreeOnTerminate := True;
end;
procedure TMPThread.DoWork;
begin
MicroProc.TraceProg;
// RegGrid.Repaint;
// PCSPGrid.Repaint;
// MemGrid.Repaint;
// PortsGrid.Repaint;
// RunStatus.Text := MicroProc.GetRunString;
// IntStatus.Text := MicroProc.GetIntString;
// RezMemo.Lines.Ad
|