- •Кафедра вычислительной техники
- •Санкт-Петербург
- •1. Техническое задание
- •2. Структурная схема разрабатываемой системы
- •3. Описание архитектуры на регистровом уровне
- •3.1. Центральный процессор
- •3.2. Сопроцессор
- •3.3. Форматы данных
- •3.4. Форматы команд
- •3.5. Способы адресации
- •3.6. Система команд
- •3.7. Команды сопроцессора
- •3.8. Организация виртуальной памяти
- •4. Структура выводов кристаллов
- •5. Временные диаграммы выполнения основных операций на шине
- •6. Описание функционирования автоматов
4. Структура выводов кристаллов
AD – совмещенная шина адреса и данных;
ALE – сигналALE используется для фиксации адреса на внешнем регистре – защелке;
HLD – запрос прямого доступа;
HLDA – подверждение прямого доступа;
INT – 16 входов запросов на прерывание;
INTA – подтверждение запроса на прерывание;
RD,WR – линии управляют чтением и записью в память;
IN,OUT – линии для управлением чтением и записью в порт;
СС0, СС1 – линии служат для сихронизации работыCPU и FPA
(00 нет операций, 01 выборкаданных, 10 запись команды в буфер, 11 запись данных);
WAIT – устанавливается в 1, когда сопроцессор закончил вычисления;
RESET –сигнал сброса;
CLC – синхронизация;
FPINT – прерывание особой ситуации сопроцессора;
FPBUSY – сигнал занятости сопроцессора.
5. Временные диаграммы выполнения основных операций на шине
Чтение из памяти.
Чтение из порта.
Запись в память.
Запись в порт.
Прерывание.
Захват шины.
Чтение блоками из памяти.
Запись блоками в память.
Запись команды в сопроцессор.
Команда передается из ЦП в сопроцессор частями. В такты 2, 3 передаются биты команды с 16 по 31, в такты 4, 5 передаются первые шестнадцать бит команды.
Выборка данных из сопроцессора и запись данных в сопроцессор.
Данные разбиваются на четыре группы и пересылаются по шине адреса-данных начиная со старших разрядов.
6. Описание функционирования автоматов
Исполнительный автомат.
7. Текст программы - модели процессора (Borland C++Builder)
#include <vcl\vcl.h>
#include <io.h>
#include <fcntl.h>
#include <limits.h>
#include "RISCMAIN.h"
#include "Contens.h"
#include "Register.h"
#include "Progcode.h"
#include "About.h"
#pragma hdrstop
#pragma link "Grids"
#pragma resource "*.dfm"
#define E(X) X->Enabled = true;
#define D(X) X->Enabled = false;
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { }
HINSTANCE MemManager;
char *Command[]={
"LB", "Прочитать байт", "REC <- <SR1+Imm>",
"LBU", "Прочитать байт без знака", "REC <- <SR1+Imm>",
"LW", "Прочитать слово", "REC <- <SR1+Imm>",
"LWU", "Прочитать слово без знака", "REC <- <SR1+Imm>",
"LDW", "Прочитать двойное слово", "REC <- <SR1+Imm>",
"SDW", "Записать двойное слово", "<SR1+Imm> <- SR2",
"SW", "Записать слово", "<SR1+Imm> <- SR2",
"SB", "Записать байт", "<SR1+Imm> <- SR2",
"ADD", "Сложение", "REC <- SR1+SR2",
"ADDC", "Сложение с переносом", "REC <- SR1+SR2",
"SUB", "Вычитание", "REC <- SR1-SR2",
"SUBB", "Вычитание с заемом", "REC <- SR1-SR2",
"MUL", "Беззнаковое умножение", "SR3 : REC <- SR1*SR2",
"MULS", "Умножение со знаком", "SR3 : REC <- SR1*SR2",
"DDIV", "Беззнаковое деление", "REC <- SR3 : SR1/SR2",
"DDIVS","Деление со знаком", "REC <- SR3 : SR1/SR2",
"DIV", "Беззнаковое деление", "REC <- SR1/SR2",
"DIVS", "Деление со знаком", "REC <- SR1/SR2",
"AND", "Логическое И", "REC <- SR1 & SR2",
"OR", "Логическое ИЛИ", "REC <- SR1 OR SR2",
"XOR", "Логическое Исключающее ИЛИ", "REC <- SR1 XOR SR2",
"NOR", "НЕ-ИЛИ", "REC <- NOT(SR1 OR SR2)",
"SLL", "Логический сдвиг влево на Imm и на SR2", "",
"SAL", "Арифметический сдвиг влево на Imm и на SR2", "",
"SLR", "Логический сдвиг вправо на Imm и на SR2", "",
"SAR", "Арифметический сдвиг вправо на Imm и на SR2", "",
"MOV", "Переслать данные", "REC <- SR1",
"MOVL", "Записать Imm в четверть, определяемую P, нижнюю половину (биты 0-31) REC", "REC <- Imm",
"MOVH", "Записать Imm в четверть, определяемую P, верхнюю половину (биты 32-63) REC", "REC <- Imm",
"J", "Переход, код условия задается вместо REC", "PC <- SR1",
"JI", "Относительный переход", "PC <- PC+Imm",
"IN", "Прочитать значение из порта SR1 в регистр REC", "",
"OUT", "Записать в порт SR1 значение из SR2", "",
"MFFL", "Прочитать состояние регистра флажков", "REC <- FL",
"MTFL", "Записать состояние регистра флажков", "FL <- SR1",
"LTR", "Загрузить указатель на TSS текущей задачи по адресу SR1", "<SR1> <- TSS",
"LIDT", "Загрузить указатель на таблицу дескрипторов прерывания (IDT) из SR1", "IDT <- SR1",
"OTSS", "Записывает в REC TSS задачи, работающей перед текущей", "REC <- TSS",
"EAR", "Прочитать неправильный адрес виртуальной памяти", "REC <- EA",
"WAIT", "Ожидать завершения вычисления сопроцессора", "",
"INT", "Вызов прерывания", ""}, *Flags[]={
"-","-","-","-","-","-","-","17",
"-","-","-","-","-","-","-","",
"-","-","-","-","-","-","-","",
"-","-","-","-","-","-","-","",
"-","-","-","-","-","-","-","",
"-","-","-","-","-","-","-","",
"-","-","-","-","-","-","-","",
"-","-","-","-","-","-","-","24",
"+","+","+","+","-","-","-","03",
"+","?+","+","+","-","-","-","04",
"+","+","+","+","-","-","-","05",
"+","?+","+","+","-","-","-","06",
"+","+","+","+","-","-","-","07",
"+","+","+","+","-","-","-","",
"+","+","+","+","-","-","-","",
"+","+","+","+","-","-","-","",
"+","+","+","+","-","-","-","",
"+","+","+","+","-","-","-","",
"+","0","+","0","-","-","-","13",
"+","0","+","0","-","-","-","14",
"+","0","+","0","-","-","-","15",
"+","0","+","0","-","-","-","16",
"+","+","+","-","-","-","-","",
"+","+","+","-","-","-","-","",
"+","+","+","-","-","-","-","",
"+","+","+","-","-","-","-","",
"-","-","-","-","-","-","-","02",
"-","-","-","-","-","-","-","00",
"-","-","-","-","-","-","-","01",
"?","?","?","?","-","+","-","",
"?","?","?","?","-","-","-","",
"-","-","-","-","-","1","-","",
"-","-","-","-","-","1","-","",
"?","?","?","?","?","?","-","",
"+","+","+","+","+","?+","-","",
"-","-","-","-","-","1","-","",
"-","-","-","-","-","1","-","",
"-","-","-","-","-","1","-","",
"-","-","-","-","-","1","-","",
"-","-","-","-","-","-","-","",
"-","-","-","+","+","-","-",""}, q[2];
void __fastcall TForm2::FormActivate(TObject *Sender)
{ int i;
Button1->Left = Width / 2 + 162;
StringGrid1->Cells[0][0] = "№";
StringGrid1->Cells[1][0] = "Мнемоника";
StringGrid1->Cells[2][0] = "Название";
StringGrid1->Cells[3][0] = "Содержание";
StringGrid1->Cells[4][0] = "Z";
StringGrid1->Cells[5][0] = "C";
StringGrid1->Cells[6][0] = "S";
StringGrid1->Cells[7][0] = "O";
StringGrid1->Cells[8][0] = "I";
StringGrid1->Cells[9][0] = "T";
StringGrid1->Cells[10][0] = "U";
StringGrid1->Cells[11][0] = "Код";
for (i=0; i<123; i+=3)
{ sprintf(q, " %d", (i+1)/3+1);
StringGrid1->Cells[0][(i+1)/3+1] = q;
StringGrid1->Cells[1][(i+1)/3+1] = Command[i];
StringGrid1->Cells[2][(i+1)/3+1] = Command[i+1];
StringGrid1->Cells[3][(i+1)/3+1] = Command[i+2];
}
for (i=0; i<328; i+=8)
{ StringGrid1->Cells[4][(i+1)/8+1] = Flags[i];
StringGrid1->Cells[5][(i+1)/8+1] = Flags[i+1];
StringGrid1->Cells[6][(i+1)/8+1] = Flags[i+2];
StringGrid1->Cells[7][(i+1)/8+1] = Flags[i+3];
StringGrid1->Cells[8][(i+1)/8+1] = Flags[i+4];
StringGrid1->Cells[9][(i+1)/8+1] = Flags[i+5];
StringGrid1->Cells[10][(i+1)/8+1] = Flags[i+6];
StringGrid1->Cells[11][(i+1)/8+1] = Flags[i+7];
}
}
void __fastcall TForm2::FormResize(TObject *Sender)
{ Button1->Left = Width / 2 + 162; }
void __fastcall TForm2::Button1Click(TObject *Sender)
{ Close(); }
class Register
{ private:
char HexValue[17];// 64-битное значение регистра (Hex)
__int64 DecValue; // 64-битное значение регистра (Dec)
public:
__fastcall Register() {};
__fastcall ~Register() {};
void __fastcall Clear(void); // Очистка регистра
void __fastcall ShowReg(int, int, int, TStringGrid*);// Показать содержимое регистра
void __fastcall ShowReg1(int, int, int, TStringGrid*);
void __fastcall LoadReg(unsigned __int64, int); // Загрузить регистр значением
void __fastcall CopyReg(Register); // Копировать значение одного регистра в другой
char* __fastcall GetHexValue(void); // Значение регистра (Hex)
__int64 __fastcall GetDecValue(int); // Значение регистра (Dec)
};
class CPU_Command
{ private:
char BinV[33]; // Двоичное представление команды
char c[30]; // Текстовое представление команды
char *ptr;
int CCode; // Код команды
public:
__fastcall CPU_Command() {};
__fastcall ~CPU_Command() {};
int __fastcall TranslateCommand(char*); // Трансляция команды (в bin-виде)
int __fastcall RegNumber(char*); // Номер регистра
int __fastcall ARegNumber(char*); // Номер регистра (в команде обращения к памяти)
int __fastcall ImmNumber(char*); // Непосредственный операнд
int __fastcall AImmNumber(char*); // Непосредственный операнд (в команде обращения к памяти)
void __fastcall TextCom(char, int);
char __fastcall TextCom(int);
char* __fastcall TextCom(void); // Текст команды
char* __fastcall Mnemonics(char*); // Выделение мнемоники из команды
char* __fastcall ComCode(void); // Команда в bin-коде
void __fastcall Code(int, int, int);
void __fastcall Execute(TStringGrid*, TStringGrid*, TStringGrid*, TRadioGroup*, TCheckBox*);
};
CPU_Command Com[100];// Максимум - программа из 100 команд
Register Reg[64]; // 32 регистра CPU и 32 регистра FPU
int CurCom, NumCom; // Номер текущей команды и число команд
char FN[100], b[100];
char StatusFlag[7], FPA_Flag[7];// Флаги: Status - Z,C,S,O,I,T,U
// FPA - B,Z,S,O,I,RC
typedef short int (__stdcall *write_byte)(unsigned long, char);
typedef char (__stdcall *read_byte)(unsigned long);
#define SaveByte(Address, Val)\
((write_byte)GetProcAddress(MemManager, "WriteByte"))(Address, Val);
#define LoadByte(Address)\
((read_byte)GetProcAddress(MemManager, "ReadByte"))(Address);
#define _Caption\
sprintf(b, "RISC CPU Modeling 1.01 - %s", FN);\
Caption = b;
// Очистка регистра
void __fastcall Register::Clear(void)
{ int i;
for (DecValue = i = 0; i < 16; i++)
HexValue[i] = '0';
}
// Показать содержимое регистра
void __fastcall Register::ShowReg(int n, int d, int s, TStringGrid *a)
{ char x[21];
if (d) // Dec
{ if (s) // Signed
sprintf(x, "%Ld", DecValue);
else // Unsigned
sprintf(x, "%Lu", DecValue);
a->Cells[1][n%32+1] = x;
}
else // Hex
a->Cells[1][n%32+1] = HexValue;
}
// Загрузить регистр значением
void __fastcall Register::LoadReg(unsigned __int64 x, int f)
{ int i;
char a[16] = {"0123456789ABCDEF"}, b;
for (i = 15; i >= 0; i--)
{ b = a[(int)(x % 16)];
HexValue[i] = f? (b == '0'? HexValue[i]: b): b;
x >>= 4;
}
DecValue = GetDecValue(64);
}
// Значение регистра (Hex)
char* __fastcall Register::GetHexValue(void)
{ return HexValue; }
// Вычисление функции 16^x
unsigned __int64 __fastcall F3(int x)
{ unsigned __int64 p = 1;
for (int i=0; i<x; i++)
p *= 16;
return p;
}
// Преобразование Hex -> Dec
int __fastcall HexDec(char s)
{ int p;
switch (s)
{ case '0': p = 0; break;
case '1': p = 1; break;
case '2': p = 2; break;
case '3': p = 3; break;
case '4': p = 4; break;
case '5': p = 5; break;
case '6': p = 6; break;
case '7': p = 7; break;
case '8': p = 8; break;
case '9': p = 9; break;
case 'A': p = 10; break;
case 'B': p = 11; break;
case 'C': p = 12; break;
case 'D': p = 13; break;
case 'E': p = 14; break;
case 'F': p = 15;
}
return p;
}
// Значение регистра (Dec) с заданным числом бит
__int64 __fastcall Register::GetDecValue(int NumberOfBits)
{ __int64 v = 0;
for (int i=0; i < (NumberOfBits >> 2); i++)
v += (unsigned __int64)(HexDec(HexValue[15 - i]) * F3(i));
return v;
}
// Копировать значение регистра Source в регистр Target
void __fastcall Register::CopyReg(Register Source)
{ for (int i=0; i<16; i++)
HexValue[i] = Source.GetHexValue()[i];
DecValue = Source.GetDecValue(64);
}
int __fastcall F(int x, int n, int f)
{ int a, i, k=0;
for (i=f; i>0; i>>=1, k++)
if (x == i)
{ a = n + k;
break;
}
return a;
}
void __fastcall CPU_Command::TextCom(char s, int x)
{ c[x] = s;
}
char __fastcall CPU_Command::TextCom(int x)
{ return c[x];
}
char* __fastcall CPU_Command::TextCom(void)
{ return c;
}
// Выделение мнемоники из команды
char* __fastcall CPU_Command::Mnemonics(char *c)
{ char *s;
int i;
ptr = c;
s = new char[6];
for (i=0; i<6; i++)
{ s[i] = *(ptr++);
if (s[i] == ' ')
{ s[i] = 0;
break;
}
}
if (i==6)
return NULL;
return s;
}
void __fastcall CPU_Command::Code(int c, int n, int f)
{ int i;
switch (f)
{ case 1: f = 2; break;
case 4: f = 16; break;
case 5: f = 32; break;
case 7: f = 128; break;
case 9: f = 512; break;
case 14: f = 16384;
}
for (i=f; i>0; i>>=1)
{ BinV[F(i,n,f)] = (char)(48+c/i);
c %= i;
}
}
// Номер регистра
int __fastcall CPU_Command::RegNumber(char *c)
{ char s[20];
int j, i = 0;
while(*ptr != 'R')
{ if (*ptr != ' ')
return -1;
ptr++;
}
ptr++;
do
s[i++] = *(ptr++);
while(s[i-1] != ',' && s[i-1] != ':' && s[i-1]);
s[--i] = 0;
for (j = 0; j < i; j++)
if (s[j] != ' ' && (s[j] < '0' || s[j] > '9'))
return -1;
return atoi(s);
}
// Номер регистра (в команде обращения к памяти)
int __fastcall CPU_Command::ARegNumber(char *c)
{ char s[20];
int j, i = 0;
while(*ptr != 'R')
{ if (*ptr != ' ' && *ptr != '(')
return -1;
ptr++;
}
ptr++;
do
s[i++] = *(ptr++);
while(s[i-1] != '+' && s[i-1]);
if (s[i-1] != '+')
return -1;
s[--i] = 0;
for (j = 0; j < i; j++)
if (s[j] != ' ' && (s[j] < '0' || s[j] > '9'))
return -1;
return atoi(s);
}
// Непосредственный операнд
int __fastcall CPU_Command::ImmNumber(char *c)
{ char s[4];
int i = 0, k;
while(*ptr == ' ' || *ptr == ',')
ptr++;
while (*ptr != ' ' && *ptr != ',' && *ptr)
s[i++] = *(ptr++);
s[i]=0;
for (k=0; k<i; k++)
if (s[k]<'0' || s[k]>'9')
return -1;
return atoi(s);
}
// Непосредственный операнд (в команде обращения к памяти)
int __fastcall CPU_Command::AImmNumber(char *c)
{ char s[4];
int i = 0, k;
while(*ptr == ' ' || *ptr == '+')
ptr++;
while (*ptr != ' ' && *ptr != ')' && *ptr)
s[i++] = *(ptr++);
s[i]=0;
while (*ptr != ',' && *ptr)
ptr++;
ptr++;
for (k=0; k<i; k++)
if (s[k]<'0' || s[k]>'9')
return -1;
return atoi(s);
}
#define CheckRegisterRange if (x<0 || x>31) return 1;
#define CODE(Q) y = 1; CCode = Q; Code(CCode,1,5); BinV[0] = '0';
// Трансляция команды (в bin-виде)
int __fastcall CPU_Command::TranslateCommand(char *c)
{ char *s;
int x, y = 0;
s = Mnemonics(c);
if (!s)
return 1;
if (!strcmp(s, "movl")) // ------------------ movl
{ CODE(0)
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
Code(0,12,4);
Code(0,17,4);
x = ImmNumber(c);
if (x<0 || x>255)
return 1;
Code(x,24,7);
x = ImmNumber(c);
if (x<0 || x>3)
return 1;
Code(x,22,1);
}
if (!strcmp(s, "movh")) // ------------------ movh
{ CODE(1)
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
Code(0,12,4);
Code(0,17,4);
x = ImmNumber(c);
if (x<0 || x>255)
return 1;
Code(x,24,7);
x = ImmNumber(c);
if (x<0 || x>3)
return 1;
Code(x,22,1);
}
if (!strcmp(s, "mov")) // ------------------ mov
{ CODE(2)
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,12,4);
Code(0,17,14);
} // -------- add, addc
if (!strcmp(s, "add") || !strcmp(s, "addc"))
{ CODE(!strcmp(s, "add")? 3: 4)
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,12,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,17,4);
Code(0,22,9);
} // -------- sub, subb
if (!strcmp(s, "sub") || !strcmp(s, "subb"))
{ CODE(!strcmp(s, "sub")? 5: 6)
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,12,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,17,4);
Code(0,22,9);
}
if (!strcmp(s, "mul")) // ------------------ mul
{ CODE(7)
x = RegNumber(c);
CheckRegisterRange
Code(x,22,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,12,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,17,4);
Code(0,27,4);
} // ------------------ and, or, xor, nor
if (!strcmp(s, "and") || !strcmp(s, "or") || !strcmp(s, "xor") || !strcmp(s, "nor"))
{ CODE(!strcmp(s, "and")? 13: !strcmp(s, "or")? 14: !strcmp(s, "xor")? 15: 16);
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,12,4);
x = RegNumber(c);
CheckRegisterRange
Code(x,17,4);
Code(0,22,9);
}
if (!strcmp(s, "sb")) // ------------------ sb
{ CODE(24)
Code(0,7,4);
x = ARegNumber(c);
CheckRegisterRange
Code(x,12,4);
x = AImmNumber(c);
if (x<0 || x>1023)
return 1;
Code(x,22,9);
x = RegNumber(c);
CheckRegisterRange
Code(x,17,4);
}
if (!strcmp(s, "lb")) // ------------------ lb
{ CODE(17)
x = RegNumber(c);
CheckRegisterRange
Code(x,7,4);
x = ARegNumber(c);
CheckRegisterRange
Code(x,12,4);
Code(0,17,4);
x = AImmNumber(c);
if (x<0 || x>1023)
return 1;
Code(x,22,9);
}
if (!y)
return 1;
BinV[32] = 0;
return 0;
}
// Команда в bin-коде
char* __fastcall CPU_Command::ComCode(void)
{ return BinV;
}
// Вычисление функции 2^x
unsigned long __fastcall F1(int x)
{ unsigned long p = 1L;
int i;
for (i=0; i<x; i++)
p *= 2L;
return p;
}
// Сохранить текст RISC CPU программы
void __fastcall TForm1::SaveButtonClick(TObject *Sender)
{ if (strcmp(OpenDialog1->FileName.c_str(), ""))
Memo1->Lines->SaveToFile(OpenDialog1->FileName);
}
// Выход из программы
void __fastcall TForm1::FileExitClick(TObject *Sender)
{ Application->Terminate();
}
void __fastcall TForm1::HelpContentsClick(TObject *Sender)
{ Form2->Button1->Left = 360 + (Form2->Width - 480) / 2;
Form2->ShowModal();
}
void __fastcall TForm1::HelpAboutClick(TObject *Sender)
{ Form5->Show();
}
void __fastcall TForm5::Button1Click(TObject *Sender)
{ Form5->Close();
}
// Загрузка текста RISC CPU программы из файла
void __fastcall TForm1::OpenButtonClick(TObject *Sender)
{ OpenDialog1->FileName = "";
OpenDialog1->Execute();
if (strcmp(OpenDialog1->FileName.c_str(), ""))
{ strcpy(FN, OpenDialog1->FileName.c_str());
_Caption
Memo1->Lines->LoadFromFile(OpenDialog1->FileName);
if (Memo1->Lines->Count)
{ E(Button4) E(TProg) E(SButton4)
}
else
{ D(Button4) D(TProg) D(SButton4)
}
}
}
// Загрузка текста RISC CPU программы из файла и ее трансляция
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{ OpenDialog1->FileName = "";
OpenDialog1->Execute();
if (strcmp(OpenDialog1->FileName.c_str(), ""))
{ strcpy(FN, OpenDialog1->FileName.c_str());
_Caption
Memo1->Lines->LoadFromFile(OpenDialog1->FileName);
if (Memo1->Lines->Count)
{ E(Button4) E(TProg) E(SButton4)
}
else
{ D(Button4) D(TProg) D(SButton4)
}
}
Button4Click(Sender);
}
void __fastcall TForm1::Memo1Change(TObject *Sender)
{ if (Memo1->Lines->Count)
{ E(Button4) E(TProg) E(SButton4)
}
else
{ D(Button4) D(TProg) D(SButton4)
}
}
// Отобразить значения флагов
void __fastcall ShowFlags(TStringGrid *b, TStringGrid *a)
{ for (int i=0; i<13; i++)
if (i>6)
a->Cells[1][i-6] = FPA_Flag[i-6];
else
b->Cells[1][i+1] = StatusFlag[i+1];
sprintf(q, "%c%c", FPA_Flag[5], FPA_Flag[6]);
a->Cells[1][6] = q;
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{ int i;
char q[4], *x[] = {"Z","C","S","O","I","T","U","B","Z","S","O","I","RC"};
MemManager = LoadLibrary("memman.dll");
if(!MemManager)
{ MessageBox(NULL, "MEMMAN.DLL not found!", "Error", 0);
Application->Terminate();
}
else
GetProcAddress(MemManager, "InitialMemory")();
strcpy(StatusFlag, "0000000");
strcpy(FPA_Flag, "0000000");
StringGrid1->Cells[0][0] = " R";
StringGrid2->Cells[0][0] = " R";
StringGrid1->Cells[1][0] = " Value";
StringGrid2->Cells[1][0] = " Value";
for (i=0; i<64; i++)
{ sprintf(q, "%2d", i);
if (i>31)
StringGrid2->Cells[0][i-31] = q;
else
StringGrid1->Cells[0][i+1] = q;
Reg[i].Clear();
Reg[i].ShowReg(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>31? StringGrid2: StringGrid1);
}
for (i=0; i<13; i++)
if (i>6)
StringGrid4->Cells[0][i-6] = x[i];
else
StringGrid3->Cells[0][i+1] = x[i];
ShowFlags(StringGrid3, StringGrid4);
}
void __fastcall TForm4::Button1Click(TObject *Sender)
{ Close(); }
// Трансляция программы
void __fastcall TForm1::Button4Click(TObject *Sender)
{ int i, f, len, ErrorStatus;
char q[20];
CurCom = 0;
len = strlen(Memo1->Lines->Text.c_str());
for (NumCom = f = i = 0; i<len; i++)
{ Com[NumCom].TextCom(Memo1->Lines->Text.c_str()[i], f);
if (Com[NumCom].TextCom(f) == 0x0d)
{ Com[NumCom++].TextCom(0, f);
i++;
f = -1;
}
f++;
}
for (ErrorStatus = i = 0; i < NumCom; i++)
if (Com[i].TranslateCommand(Com[i].TextCom()))
{ ErrorStatus = 1;
break;
}
if (ErrorStatus) // Есть ошибка
{ sprintf(q, "Error in lines %d", i+1);
ListBox1->Clear();
Edit5->Text = q;
Edit1->Text = ""; Edit2->Text = "";
Edit3->Text = ""; Edit4->Text = "";
D(ListBox1)
D(RunF9) D(RunButton) D(Button7)
D(Button5) D(Programcode1) D(SButton5)
D(TopButton) D(FCom) D(Button6)
D(EndButton) D(LCom)
D(PreviousButton) D(BitBtn1) D(PCom)
D(NextButton) D(BitBtn2) D(NCom)
D(ExecuteButton) D(Button1) D(EC1)
}
else // Нет ошибок
{ sprintf(q, "Error not found");
Edit5->Text = q;
E(ListBox1)
ListBox1->Clear();
E(RunF9) E(RunButton) E(Button7)
E(Button5) E(Programcode1) E(SButton5)
for (i=0; i<NumCom; i++)
ListBox1->Items->Add(Com[i].TextCom());
Edit1->Text = ""; Edit3->Text = "";
Edit2->Text = Com[0].TextCom();
Edit4->Text = Com[0].ComCode();
E(ExecuteButton) E(Button1) E(EC1)
E(TopButton) E(FCom) E(Button6)
E(EndButton) E(LCom)
if (NumCom == 1)
{ D(TopButton) D(FCom) D(Button6)
D(EndButton) D(LCom)
}
if (!NumCom)
{ Edit1->Text = ""; Edit2->Text = "";
Edit3->Text = ""; Edit4->Text = "";
D(TopButton) D(FCom) D(Button6)
D(EndButton) D(LCom)
D(PreviousButton) D(BitBtn1)
D(NextButton) D(BitBtn2)
D(ExecuteButton) D(Button1) D(EC1)
}
D(PreviousButton) D(BitBtn1) D(PCom)
D(NextButton) D(BitBtn2) D(NCom)
if (NumCom > 1)
{ E(NextButton) E(BitBtn2) E(NCom)
Edit3->Text = Com[1].TextCom();
}
}
}
void __fastcall TForm1::SaveAs1Click(TObject *Sender)
{ SaveDialog1->FileName = "";
SaveDialog1->Execute();
if (strcmp(SaveDialog1->FileName.c_str(), ""))
{ Memo1->Lines->SaveToFile(SaveDialog1->FileName);
strcpy(FN, SaveDialog1->FileName.c_str());
_Caption
}
}
// Программный код
void __fastcall TForm1::Button5Click(TObject *Sender)
{ char a[4] = {0,0,0,0};
int i;
Form3->Show();
Form3->StringGrid2->RowCount = NumCom + 1;
Form3->StringGrid2->Cells[0][0] = "№";
Form3->StringGrid2->Cells[1][0] = "Program text";
Form3->StringGrid2->Cells[2][0] = "Program code";
for (i = 0; i < NumCom; i++)
{ sprintf(a, "%3d", i+1);
Form3->StringGrid2->Cells[0][i+1] = a;
Form3->StringGrid2->Cells[1][i+1] = Com[i].TextCom();
Form3->StringGrid2->Cells[2][i+1] = Com[i].ComCode();
}
}
void __fastcall TForm3::Button1Click(TObject *Sender)
{ Close();
}
// Преобразование бинарного числа в десятичное
// a - начало, n - количество бит
int F2(int a, int n, char *c)
{ int i, k = 0;
for (i=n-1; i>=0; i--)
k += (c[a++]-48)*(int)F1(i);
return k;
}
// Выполнение текущей команды
void __fastcall CPU_Command::Execute(TStringGrid *A, TStringGrid *B, TStringGrid *C, TRadioGroup *D, TCheckBox *E)
{ int REC, SR1, SR2, SR3, P, Imm;
__int64 sign;
char value;
unsigned __int64 rec, sr1, sr2, t;
unsigned long address;
long double overflow;
switch (CCode)
{ case 0: // ------------------------------------ movl
{ REC = F2(7,5,BinV);
P = F2(22,2,BinV);
Imm = F2(24,8,BinV);
Reg[REC].LoadReg(Imm << (P << 3), 1);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
} break;
case 1: // ------------------------------------ movh
{ REC = F2(7,5,BinV);
P = F2(22,2,BinV);
Imm = F2(24,8,BinV);
Reg[REC].LoadReg((__int64)Imm << 32 << (P << 3), 1);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
} break;
case 2: // ------------------------------------ mov
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
Reg[REC].CopyReg(Reg[SR1]);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
} break;
case 3: // ------------------------------------ add
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
SR2 = F2(17,5,BinV);
sr1 = Reg[SR1].GetDecValue(64);
sr2 = Reg[SR2].GetDecValue(64);
rec = sr1 + sr2;
overflow = (long double) sr1 + (long double) sr2;
Reg[REC].LoadReg(rec, 0);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
StatusFlag[1] = rec? '0': '1'; // нулевой результат (Z)
StatusFlag[4] = overflow > 18446744073709551615L? '1': '0'; // переполнение (O)
ShowFlags(B, C);
} break;
case 4: // ------------------------------------ addc
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
SR2 = F2(17,5,BinV);
sr1 = Reg[SR1].GetDecValue(64);
sr2 = Reg[SR2].GetDecValue(64);
rec = sr1 + sr2 + (__int64)(StatusFlag[2] - 48);
overflow = (long double) sr1 + (long double) sr2 + (long double)(StatusFlag[2] - 48);
Reg[REC].LoadReg(rec, 0);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
StatusFlag[1] = rec? '0': '1'; // нулевой результат (Z)
StatusFlag[4] = overflow > 18446744073709551615L? '1': '0'; // переполнение (O)
ShowFlags(B, C);
} break;
case 5: // ------------------------------------ sub
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
SR2 = F2(17,5,BinV);
sr1 = Reg[SR1].GetDecValue(64);
sr2 = Reg[SR2].GetDecValue(64);
rec = sr1 - sr2;
sign = (__int64)sr1 - (__int64)sr2;
Reg[REC].LoadReg(rec, 0);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
StatusFlag[1] = rec? '0': '1'; // нулевой результат (Z)
StatusFlag[3] = sign>0? '0': '1'; // знак (S)
ShowFlags(B, C);
} break;
case 6: // ------------------------------------ subb
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
SR2 = F2(17,5,BinV);
sr1 = Reg[SR1].GetDecValue(64);
sr2 = Reg[SR2].GetDecValue(64);
rec = sr1 - sr2 - (__int64)(StatusFlag[2] - 48);
sign = (__int64)sr1 - (__int64)sr2 - (__int64)(StatusFlag[2] - 48);
Reg[REC].LoadReg(rec, 0);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
StatusFlag[1] = rec? '0': '1'; // нулевой результат (Z)
StatusFlag[3] = sign>0? '0': '1'; // знак (S)
ShowFlags(B, C);
} break;
case 7: // ------------------------------------ mul
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
SR2 = F2(17,5,BinV);
SR3 = F2(22,5,BinV);
sr1 = Reg[SR1].GetDecValue(64);
sr2 = Reg[SR2].GetDecValue(64);
rec = sr1 * sr2;
overflow = (long double) sr1 * (long double) sr2;
t = rec / F3(8);
Reg[SR3].LoadReg(t, 0);
Reg[REC].LoadReg(rec - t * F3(8), 0);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
Reg[SR3].ShowReg(SR3, D->ItemIndex, E->Checked, A);
StatusFlag[1] = rec? '0': '1'; // нулевой результат (Z)
StatusFlag[4] = overflow > 18446744073709551615L? '1': '0'; // переполнение (O)
ShowFlags(B, C);
} break;
#define Logic1\
REC = F2(7,5,BinV);\
SR1 = F2(12,5,BinV);\
SR2 = F2(17,5,BinV);\
sr1 = Reg[SR1].GetDecValue(64);\
sr2 = Reg[SR2].GetDecValue(64);
#define Logic2\
Reg[REC].LoadReg(rec, 0);\
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);\
StatusFlag[1] = rec? '0': '1'; /* нулевой результат (Z) */\
StatusFlag[2] = '0'; /* перенос из старшего разряда (C) */\
StatusFlag[4] = '0'; /* переполнение (O) */\
ShowFlags(B, C);
case 13: // ------------------------------------ and
{ Logic1
rec = sr1 & sr2;
Logic2
} break;
case 14: // ------------------------------------ or
{ Logic1
rec = sr1 | sr2;
Logic2
} break;
case 15: // -7----------------------------------- xor
{ Logic1
rec = sr1 ^ sr2;
Logic2
} break;
case 16: // ------------------------------------ nor
{ Logic1
rec = ~(sr1 | sr2);
Logic2
} break;
case 24: // ------------------------------------ sb
{ SR1 = F2(12,5,BinV);
SR2 = F2(17,5,BinV);
Imm = F2(22,10,BinV);
sr1 = Reg[SR1].GetDecValue(32);
sr2 = Reg[SR2].GetDecValue(8);
value = (char)sr2;
address = (unsigned long)((unsigned __int64)Imm + sr1);
SaveByte(address, value);
} break;
case 17: // ------------------------------------ lb
{ REC = F2(7,5,BinV);
SR1 = F2(12,5,BinV);
Imm = F2(22,10,BinV);
sr1 = Reg[SR1].GetDecValue(32);
address = (unsigned long)((unsigned __int64)Imm + sr1);
value = LoadByte(address);
Reg[REC].LoadReg(value, 0);
Reg[REC].ShowReg(REC, D->ItemIndex, E->Checked, A);
} break;
}
}
// Выполнить текущую команду
void __fastcall TForm1::Button1Click(TObject *Sender)
{ Com[CurCom].Execute(StringGrid1, StringGrid3, StringGrid4, RadioGroup1, CheckBox1);
if (CurCom < NumCom - 1)
{ Edit1->Text = Com[CurCom++].TextCom();
Edit2->Text = Com[CurCom].TextCom();
Edit4->Text = Com[CurCom].ComCode();
if (CurCom == NumCom-1)
{ Edit3->Text = "";
D(NextButton) D(BitBtn2) D(NCom)
}
else
{ Edit3->Text = Com[CurCom+1].TextCom();
E(PreviousButton) E(BitBtn1) E(PCom)
}
}
}
// Перейти к первой команде
void __fastcall TForm1::TopButtonClick(TObject *Sender)
{ CurCom = 1;
Edit3->Text = Com[CurCom--].TextCom();
Edit2->Text = Com[CurCom].TextCom();
Edit4->Text = Com[CurCom].ComCode();
Edit1->Text = "";
D(PreviousButton) D(BitBtn1) D(PCom)
E(NextButton) E(BitBtn2) E(NCom)
}
// Перейти к последней команде
void __fastcall TForm1::EndButtonClick(TObject *Sender)
{ CurCom = NumCom-2;
Edit1->Text = Com[CurCom++].TextCom();
Edit2->Text = Com[CurCom].TextCom();
Edit4->Text = Com[CurCom].ComCode();
Edit3->Text = "";
D(NextButton) D(BitBtn2) D(NCom)
E(PreviousButton) E(BitBtn1) E(PCom)
}
// Перейти к предыдущей команде
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{ Edit3->Text = Com[CurCom--].TextCom();
Edit2->Text = Com[CurCom].TextCom();
Edit4->Text = Com[CurCom].ComCode();
if (!CurCom)
{ Edit1->Text = "";
D(PreviousButton) D(BitBtn1) D(PCom)
if (NumCom > 1)
{ E(NextButton) E(BitBtn2) E(NCom)
}
}
else
{ Edit1->Text = Com[CurCom-1].TextCom();
E(NextButton) E(BitBtn2) E(NCom)
}
}
// Перейти к следующей команде
void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{ Edit1->Text = Com[CurCom++].TextCom();
Edit2->Text = Com[CurCom].TextCom();
Edit4->Text = Com[CurCom].ComCode();
if (CurCom == NumCom-1)
{ Edit3->Text = "";
D(NextButton) D(BitBtn2) D(NCom)
if (NumCom > 1)
{ E(PreviousButton) E(BitBtn1) E(PCom)
}
}
else
{ Edit3->Text = Com[CurCom+1].TextCom();
E(PreviousButton) E(BitBtn1) E(PCom)
}
}
// Reset registers
void __fastcall TForm1::Button3Click(TObject *Sender)
{ for (int i=0; i<64; i++)
{ Reg[i].Clear();
Reg[i].ShowReg(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>31? StringGrid2: StringGrid1);
}
}
// Run - запуск программы на выполнение
// Останов по Breakpoint
void __fastcall TForm1::RunButtonClick(TObject *Sender)
{ int i;
for (i=CurCom; i<NumCom && !ListBox1->Selected[i]; i++)
{ Com[CurCom].Execute(StringGrid1, StringGrid3, StringGrid4, RadioGroup1, CheckBox1);
if (CurCom < NumCom - 1)
{ Edit1->Text = Com[CurCom++].TextCom();
Edit2->Text = Com[CurCom].TextCom();
Edit4->Text = Com[CurCom].ComCode();
if (CurCom == NumCom-1)
{ Edit3->Text = "";
D(NextButton) D(BitBtn2) D(NCom)
if (NumCom > 1)
{ E(PreviousButton) E(BitBtn1) E(PCom)
}
}
else
{ Edit3->Text = Com[CurCom+1].TextCom();
E(PreviousButton) E(BitBtn1) E(PCom)
}
}
}
}
void __fastcall TForm3::StringGrid2Click(TObject *Sender)
{ int i, j, n = Form3->StringGrid2->Row - 1;
char a[3] = {0,0,0};
for (i=0; i<32; i++)
StringGrid1->Cells[i][0] = Com[n].ComCode()[i];
for (i=j=0; j<6; j++)
i += int(Com[n].ComCode()[j+1]-48) << (5-j);
HeaderControl1->Visible = (i==7)? false: true;
sprintf(a, "%d", i);
Edit1->Text = a;
}
void __fastcall TForm1::RadioGroup1Click(TObject *Sender)
{ if (!RadioGroup1->ItemIndex)
D(CheckBox1)
else
E(CheckBox1)
for (int i=0; i<64; i++)
Reg[i].ShowReg(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>31? StringGrid2: StringGrid1);
GroupBox1->Caption = RadioGroup1->ItemIndex? (AnsiString)"CPU Registers (Dec 64-bit)": (AnsiString)"CPU Registers (Hex 64-bit)";
GroupBox3->Caption = RadioGroup1->ItemIndex? (AnsiString)"FPU Registers (Dec 64-bit)": (AnsiString)"FPU Registers (Hex 64-bit)";
}
// Показать содержимое регистра
void __fastcall Register::ShowReg1(int n, int d, int s, TStringGrid *a)
{ char x[21];
if (d) // Dec
{ if (s) // Signed
sprintf(x, "%Ld", DecValue);
else // Unsigned
sprintf(x, "%Lu", DecValue);
a->Cells[1][n%16+1] = x;
}
else // Hex
a->Cells[1][n%16+1] = HexValue;
}
void __fastcall TForm4::RadioGroup1Click(TObject *Sender)
{ int i;
if (!RadioGroup1->ItemIndex)
D(CheckBox1)
else
E(CheckBox1)
for (i=0; i<32; i++)
Reg[i].ShowReg1(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>15? StringGrid2: StringGrid1);
for (i=32; i<64; i++)
Reg[i].ShowReg1(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>47? StringGrid4: StringGrid3);
GroupBox1->Caption = RadioGroup1->ItemIndex? "CPU Registers (Dec 64-bit)": "CPU Registers (Hex 64-bit)";
GroupBox2->Caption = RadioGroup1->ItemIndex? "FPU Registers (Dec 64-bit)": "FPU Registers (Hex 64-bit)";
}
void __fastcall TForm4::CheckBox1Click(TObject *Sender)
{ int i;
for (i=0; i<32; i++)
Reg[i].ShowReg1(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>15? StringGrid2: StringGrid1);
for (i=32; i<64; i++)
Reg[i].ShowReg1(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>47? StringGrid4: StringGrid3);
}
void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{ for (int i=0; i<64; i++)
Reg[i].ShowReg(i, RadioGroup1->ItemIndex, CheckBox1->Checked, i>31? StringGrid2: StringGrid1);
}
// CPU и FPU регистры (полный вид)
void __fastcall TForm1::Button2Click(TObject *Sender)
{ int i;
char q[4];
Form4->Show();
Form4->RadioGroup1Click(Sender);
for (i=0; i<64; i++)
{ sprintf(q, "R%d", i);
if (i<16) Form4->StringGrid1->Cells[0][i+1] = q;
if (i>=16 && i<32) Form4->StringGrid2->Cells[0][i-15] = q;
if (i>=32 && i<48) Form4->StringGrid3->Cells[0][i-31] = q;
if (i>=48) Form4->StringGrid4->Cells[0][i-47] = q;
}
Form4->StringGrid1->Cells[1][0] = " Value";
Form4->StringGrid2->Cells[1][0] = " Value";
Form4->StringGrid3->Cells[1][0] = " Value";
Form4->StringGrid4->Cells[1][0] = " Value";
}