BESM6: Implemented WRU when no local console, added binary punchtape mode,
translated some comments.
This commit is contained in:
parent
c2cef3c051
commit
8f6e849ecf
7 changed files with 302 additions and 173 deletions
|
@ -65,16 +65,27 @@ int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
|
||||||
|
|
||||||
extern const char *scp_errors[];
|
extern const char *scp_errors[];
|
||||||
|
|
||||||
/* нехранящие биты ГРП должны сбрасываться путем обнуления тех регистров,
|
/* Wired (non-registered) bits of interrupt registers (GRP and PRP)
|
||||||
* сборкой которых они являются
|
* cannot be cleared by writing to the GRP and must be cleared by clearing
|
||||||
|
* the registers generating the corresponding interrupts.
|
||||||
*/
|
*/
|
||||||
#define GRP_WIRED_BITS 01400743700000000LL
|
#define GRP_WIRED_BITS (GRP_DRUM1_FREE | GRP_DRUM2_FREE |\
|
||||||
|
GRP_CHAN3_DONE | GRP_CHAN4_DONE |\
|
||||||
|
GRP_CHAN5_DONE | GRP_CHAN6_DONE |\
|
||||||
|
GRP_CHAN3_FREE | GRP_CHAN4_FREE |\
|
||||||
|
GRP_CHAN5_FREE | GRP_CHAN6_FREE |\
|
||||||
|
GRP_CHAN7_FREE )
|
||||||
|
|
||||||
#define PRP_WIRED_BITS 0770000
|
/* So far irrelevant as none of the devices -
|
||||||
|
* punchcard I/O and punchtape output - had been implemented.
|
||||||
|
*/
|
||||||
|
#define PRP_WIRED_BITS (PRP_UVVK1_END | PRP_UVVK2_END |\
|
||||||
|
PRP_PCARD1_CHECK | PRP_PCARD2_CHECK |\
|
||||||
|
PRP_PCARD1_PUNCH | PRP_PCARD2_PUNCH |\
|
||||||
|
PRP_PTAPE1_PUNCH | PRP_PTAPE2_PUNCH )
|
||||||
|
|
||||||
int corr_stack;
|
int corr_stack;
|
||||||
int redraw_panel;
|
int redraw_panel;
|
||||||
uint32 delay;
|
|
||||||
jmp_buf cpu_halt;
|
jmp_buf cpu_halt;
|
||||||
|
|
||||||
t_stat cpu_examine (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_examine (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
|
@ -94,13 +105,13 @@ t_stat cpu_req (UNIT *u, int32 val, char *cptr, void *desc);
|
||||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MEMSIZE) };
|
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MEMSIZE) };
|
||||||
|
|
||||||
REG cpu_reg[] = {
|
REG cpu_reg[] = {
|
||||||
{ "СчАС", &PC, 8, 15, 0, 1 }, /* счётчик адреса команды */
|
{ "СчАС", &PC, 8, 15, 0, 1 }, /* счётчик адреса команды */
|
||||||
{ "РК", &RK, 8, 24, 0, 1 }, /* регистр выполняемой команды */
|
{ "РК", &RK, 8, 24, 0, 1 }, /* регистр выполняемой команды */
|
||||||
{ "Аисп", &Aex, 8, 15, 0, 1 }, /* исполнительный адрес */
|
{ "Аисп", &Aex, 8, 15, 0, 1 }, /* исполнительный адрес */
|
||||||
{ "СМ", &ACC, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* сумматор */
|
{ "СМ", &ACC, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* сумматор */
|
||||||
{ "РМР", &RMR, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* регистр младших разрядов */
|
{ "РМР", &RMR, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* регистр младших разрядов */
|
||||||
{ "РАУ", &RAU, 2, 6, 0, 1 }, /* режимы АУ */
|
{ "РАУ", &RAU, 2, 6, 0, 1 }, /* режимы АУ */
|
||||||
{ "М1", &M[1], 8, 15, 0, 1 }, /* регистры-модификаторы */
|
{ "М1", &M[1], 8, 15, 0, 1 }, /* регистры-модификаторы */
|
||||||
{ "М2", &M[2], 8, 15, 0, 1 },
|
{ "М2", &M[2], 8, 15, 0, 1 },
|
||||||
{ "М3", &M[3], 8, 15, 0, 1 },
|
{ "М3", &M[3], 8, 15, 0, 1 },
|
||||||
{ "М4", &M[4], 8, 15, 0, 1 },
|
{ "М4", &M[4], 8, 15, 0, 1 },
|
||||||
|
@ -114,24 +125,24 @@ REG cpu_reg[] = {
|
||||||
{ "М14", &M[014], 8, 15, 0, 1 },
|
{ "М14", &M[014], 8, 15, 0, 1 },
|
||||||
{ "М15", &M[015], 8, 15, 0, 1 },
|
{ "М15", &M[015], 8, 15, 0, 1 },
|
||||||
{ "М16", &M[016], 8, 15, 0, 1 },
|
{ "М16", &M[016], 8, 15, 0, 1 },
|
||||||
{ "М17", &M[017], 8, 15, 0, 1 }, /* указатель магазина */
|
{ "М17", &M[017], 8, 15, 0, 1 }, /* указатель магазина */
|
||||||
{ "М20", &M[020], 8, 15, 0, 1 }, /* MOD - модификатор адреса */
|
{ "М20", &M[020], 8, 15, 0, 1 }, /* MOD - модификатор адреса */
|
||||||
{ "М21", &M[021], 8, 15, 0, 1 }, /* PSW - режимы УУ */
|
{ "М21", &M[021], 8, 15, 0, 1 }, /* PSW - режимы УУ */
|
||||||
{ "М27", &M[027], 8, 15, 0, 1 }, /* SPSW - упрятывание режимов УУ */
|
{ "М27", &M[027], 8, 15, 0, 1 }, /* SPSW - упрятывание режимов УУ */
|
||||||
{ "М32", &M[032], 8, 15, 0, 1 }, /* ERET - адрес возврата из экстракода */
|
{ "М32", &M[032], 8, 15, 0, 1 }, /* ERET - адрес возврата из экстракода */
|
||||||
{ "М33", &M[033], 8, 15, 0, 1 }, /* IRET - адрес возврата из прерывания */
|
{ "М33", &M[033], 8, 15, 0, 1 }, /* IRET - адрес возврата из прерывания */
|
||||||
{ "М34", &M[034], 8, 16, 0, 1 }, /* IBP - адрес прерывания по выполнению */
|
{ "М34", &M[034], 8, 16, 0, 1 }, /* IBP - адрес прерывания по выполнению */
|
||||||
{ "М35", &M[035], 8, 16, 0, 1 }, /* DWP - адрес прерывания по чтению/записи */
|
{ "М35", &M[035], 8, 16, 0, 1 }, /* DWP - адрес прерывания по чтению/записи */
|
||||||
{ "РУУ", &RUU, 2, 9, 0, 1 }, /* ПКП, ПКЛ, РежЭ, РежПр, ПрИК, БРО, ПрК */
|
{ "РУУ", &RUU, 2, 9, 0, 1 }, /* ПКП, ПКЛ, РежЭ, РежПр, ПрИК, БРО, ПрК */
|
||||||
{ "ГРП", &GRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* главный регистр прерываний */
|
{ "ГРП", &GRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* главный регистр прерываний */
|
||||||
{ "МГРП", &MGRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* маска ГРП */
|
{ "МГРП", &MGRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* маска ГРП */
|
||||||
{ "ПРП", &PRP, 8, 24, 0, 1 }, /* периферийный регистр прерываний */
|
{ "ПРП", &PRP, 8, 24, 0, 1 }, /* периферийный регистр прерываний */
|
||||||
{ "МПРП", &MPRP, 8, 24, 0, 1 }, /* маска ПРП */
|
{ "МПРП", &MPRP, 8, 24, 0, 1 }, /* маска ПРП */
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
MTAB cpu_mod[] = {
|
MTAB cpu_mod[] = {
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL, "Display idle detection mode" },
|
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL, "Enables idle detection mode" },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL, NULL, "Disables idle detection" },
|
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL, NULL, "Disables idle detection" },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "REQ", &cpu_req, NULL, NULL, "Sends a request interrupt" },
|
{ MTAB_XTD|MTAB_VDV, 0, NULL, "REQ", &cpu_req, NULL, NULL, "Sends a request interrupt" },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "PANEL", "PANEL", &besm6_init_panel, NULL, NULL, "Displays graphical panel" },
|
{ MTAB_XTD|MTAB_VDV, 0, "PANEL", "PANEL", &besm6_init_panel, NULL, NULL, "Displays graphical panel" },
|
||||||
|
@ -148,16 +159,16 @@ DEVICE cpu_dev = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* REG: псевдоустройство, содержащее латинские синонимы всех регистров.
|
* REG: A pseudo-device containing Latin synonyms of all CPU registers.
|
||||||
*/
|
*/
|
||||||
REG reg_reg[] = {
|
REG reg_reg[] = {
|
||||||
{ "PC", &PC, 8, 15, 0, 1 }, /* счётчик адреса команды */
|
{ "PC", &PC, 8, 15, 0, 1 }, /* program counter */
|
||||||
{ "RK", &RK, 8, 24, 0, 1 }, /* регистр выполняемой команды */
|
{ "RK", &RK, 8, 24, 0, 1 }, /* instruction register */
|
||||||
{ "Aex", &Aex, 8, 15, 0, 1 }, /* исполнительный адрес */
|
{ "Aex", &Aex, 8, 15, 0, 1 }, /* effective address */
|
||||||
{ "ACC", &ACC, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* сумматор */
|
{ "ACC", &ACC, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* accumulator */
|
||||||
{ "RMR", &RMR, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* регистр младших разрядов */
|
{ "RMR", &RMR, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* LSB register */
|
||||||
{ "RAU", &RAU, 2, 6, 0, 1 }, /* режимы АУ */
|
{ "RAU", &RAU, 2, 6, 0, 1 }, /* ALU modes */
|
||||||
{ "M1", &M[1], 8, 15, 0, 1 }, /* регистры-модификаторы */
|
{ "M1", &M[1], 8, 15, 0, 1 }, /* index (modifier) registers */
|
||||||
{ "M2", &M[2], 8, 15, 0, 1 },
|
{ "M2", &M[2], 8, 15, 0, 1 },
|
||||||
{ "M3", &M[3], 8, 15, 0, 1 },
|
{ "M3", &M[3], 8, 15, 0, 1 },
|
||||||
{ "M4", &M[4], 8, 15, 0, 1 },
|
{ "M4", &M[4], 8, 15, 0, 1 },
|
||||||
|
@ -171,19 +182,19 @@ REG reg_reg[] = {
|
||||||
{ "M14", &M[014], 8, 15, 0, 1 },
|
{ "M14", &M[014], 8, 15, 0, 1 },
|
||||||
{ "M15", &M[015], 8, 15, 0, 1 },
|
{ "M15", &M[015], 8, 15, 0, 1 },
|
||||||
{ "M16", &M[016], 8, 15, 0, 1 },
|
{ "M16", &M[016], 8, 15, 0, 1 },
|
||||||
{ "M17", &M[017], 8, 15, 0, 1 }, /* указатель магазина */
|
{ "M17", &M[017], 8, 15, 0, 1 }, /* also the stack pointer */
|
||||||
{ "M20", &M[020], 8, 15, 0, 1 }, /* MOD - модификатор адреса */
|
{ "M20", &M[020], 8, 15, 0, 1 }, /* MOD - address modifier register */
|
||||||
{ "M21", &M[021], 8, 15, 0, 1 }, /* PSW - режимы УУ */
|
{ "M21", &M[021], 8, 15, 0, 1 }, /* PSW - CU modes */
|
||||||
{ "M27", &M[027], 8, 15, 0, 1 }, /* SPSW - упрятывание режимов УУ */
|
{ "M27", &M[027], 8, 15, 0, 1 }, /* SPSW - saved CU modes */
|
||||||
{ "M32", &M[032], 8, 15, 0, 1 }, /* ERET - адрес возврата из экстракода */
|
{ "M32", &M[032], 8, 15, 0, 1 }, /* ERET - extracode return address */
|
||||||
{ "M33", &M[033], 8, 15, 0, 1 }, /* IRET - адрес возврата из прерывания */
|
{ "M33", &M[033], 8, 15, 0, 1 }, /* IRET - interrupt return address */
|
||||||
{ "M34", &M[034], 8, 16, 0, 1 }, /* IBP - адрес прерывания по выполнению */
|
{ "M34", &M[034], 8, 16, 0, 1 }, /* IBP - instruction bkpt address */
|
||||||
{ "M35", &M[035], 8, 16, 0, 1 }, /* DWP - адрес прерывания по чтению/записи */
|
{ "M35", &M[035], 8, 16, 0, 1 }, /* DWP - watchpoint address */
|
||||||
{ "RUU", &RUU, 2, 9, 0, 1 }, /* ПКП, ПКЛ, РежЭ, РежПр, ПрИК, БРО, ПрК */
|
{ "RUU", &RUU, 2, 9, 0, 1 }, /* execution modes */
|
||||||
{ "GRP", &GRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* главный регистр прерываний */
|
{ "GRP", &GRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* main interrupt reg */
|
||||||
{ "MGRP", &MGRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* маска ГРП */
|
{ "MGRP", &MGRP, 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* mask of the above */
|
||||||
{ "PRP", &PRP, 8, 24, 0, 1 }, /* периферийный регистр прерываний */
|
{ "PRP", &PRP, 8, 24, 0, 1 }, /* peripheral interrupt reg */
|
||||||
{ "MPRP", &MPRP, 8, 24, 0, 1 }, /* маска ПРП */
|
{ "MPRP", &MPRP, 8, 24, 0, 1 }, /* mask of the above*/
|
||||||
|
|
||||||
{ "BRZ0", &BRZ[0], 8, 50, 0, 1, NULL, NULL, REG_VMIO },
|
{ "BRZ0", &BRZ[0], 8, 50, 0, 1, NULL, NULL, REG_VMIO },
|
||||||
{ "BRZ1", &BRZ[1], 8, 50, 0, 1, NULL, NULL, REG_VMIO },
|
{ "BRZ1", &BRZ[1], 8, 50, 0, 1, NULL, NULL, REG_VMIO },
|
||||||
|
@ -245,7 +256,7 @@ char sim_name[] = "БЭСМ-6";
|
||||||
|
|
||||||
REG *sim_PC = &cpu_reg[0];
|
REG *sim_PC = &cpu_reg[0];
|
||||||
|
|
||||||
int32 sim_emax = 1; /* максимальное количество слов в машинной команде */
|
int32 sim_emax = 1; /* max number of addressable units per instruction */
|
||||||
|
|
||||||
DEVICE *sim_devices[] = {
|
DEVICE *sim_devices[] = {
|
||||||
&cpu_dev,
|
&cpu_dev,
|
||||||
|
@ -261,27 +272,27 @@ DEVICE *sim_devices[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *sim_stop_messages[] = {
|
const char *sim_stop_messages[] = {
|
||||||
"Неизвестная ошибка", /* Unknown error */
|
"Неизвестная ошибка", /* Unknown error */
|
||||||
"Останов", /* STOP */
|
"Останов", /* STOP */
|
||||||
"Точка останова", /* Emulator breakpoint */
|
"Точка останова", /* Emulator breakpoint */
|
||||||
"Точка останова по считыванию", /* Emulator read watchpoint */
|
"Точка останова по считыванию", /* Emulator read watchpoint */
|
||||||
"Точка останова по записи", /* Emulator write watchpoint */
|
"Точка останова по записи", /* Emulator write watchpoint */
|
||||||
"Выход за пределы памяти", /* Run out end of memory */
|
"Выход за пределы памяти", /* Run out end of memory */
|
||||||
"Запрещенная команда", /* Invalid instruction */
|
"Запрещенная команда", /* Invalid instruction */
|
||||||
"Контроль команды", /* A data-tagged word fetched */
|
"Контроль команды", /* A data-tagged word fetched */
|
||||||
"Команда в чужом листе", /* Paging error during fetch */
|
"Команда в чужом листе", /* Paging error during fetch */
|
||||||
"Число в чужом листе", /* Paging error during load/store */
|
"Число в чужом листе", /* Paging error during load/store */
|
||||||
"Контроль числа МОЗУ", /* RAM parity error */
|
"Контроль числа МОЗУ", /* RAM parity error */
|
||||||
"Контроль числа БРЗ", /* Write cache parity error */
|
"Контроль числа БРЗ", /* Write cache parity error */
|
||||||
"Переполнение АУ", /* Arith. overflow */
|
"Переполнение АУ", /* Arith. overflow */
|
||||||
"Деление на нуль", /* Division by zero or denorm */
|
"Деление на нуль", /* Division by zero or denorm */
|
||||||
"Двойное внутреннее прерывание", /* SIMH: Double internal interrupt */
|
"Двойное внутреннее прерывание", /* SIMH: Double internal interrupt */
|
||||||
"Чтение неформатированного барабана", /* Reading unformatted drum */
|
"Чтение неформатированного барабана", /* Reading unformatted drum */
|
||||||
"Чтение неформатированного диска", /* Reading unformatted disk */
|
"Чтение неформатированного диска", /* Reading unformatted disk */
|
||||||
"Останов по КРА", /* Hardware breakpoint */
|
"Останов по КРА", /* Hardware breakpoint */
|
||||||
"Останов по считыванию", /* Load watchpoint */
|
"Останов по считыванию", /* Load watchpoint */
|
||||||
"Останов по записи", /* Store watchpoint */
|
"Останов по записи", /* Store watchpoint */
|
||||||
"Не реализовано", /* Unimplemented I/O or special reg. access */
|
"Не реализовано", /* Unimplemented I/O or special reg. access */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -328,7 +339,7 @@ t_stat cpu_reset (DEVICE *dptr)
|
||||||
for (i=0; i<NREGS; ++i)
|
for (i=0; i<NREGS; ++i)
|
||||||
M[i] = 0;
|
M[i] = 0;
|
||||||
|
|
||||||
/* Устройства ввода с перфокарт не готовы */
|
/* Punchcard readers not yet implemented thus not ready */
|
||||||
READY2 |= 042000000;
|
READY2 |= 042000000;
|
||||||
|
|
||||||
/* Регистр 17: БлП, БлЗ, ПОП, ПОК, БлПр */
|
/* Регистр 17: БлП, БлЗ, ПОП, ПОК, БлПр */
|
||||||
|
@ -435,8 +446,8 @@ static void cmd_002 ()
|
||||||
MGRP = ACC;
|
MGRP = ACC;
|
||||||
break;
|
break;
|
||||||
case 037:
|
case 037:
|
||||||
/* Гашение главного регистра прерываний */
|
/* Clearing the main interrupt register: */
|
||||||
/* нехранящие биты невозможно погасить */
|
/* it is impossible to clear wired (stateless) bits this way */
|
||||||
GRP &= ACC | GRP_WIRED_BITS;
|
GRP &= ACC | GRP_WIRED_BITS;
|
||||||
break;
|
break;
|
||||||
case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71:
|
case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71:
|
||||||
|
@ -471,8 +482,7 @@ static void cmd_002 ()
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ((Aex & 0340) == 0140) {
|
if ((Aex & 0340) == 0140) {
|
||||||
/* TODO: управление блокировкой схемы
|
/* TODO: watchdog reset mechanism */
|
||||||
* автоматического запуска */
|
|
||||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||||
}
|
}
|
||||||
/* Неиспользуемые адреса */
|
/* Неиспользуемые адреса */
|
||||||
|
@ -493,8 +503,13 @@ static void cmd_033 ()
|
||||||
#endif
|
#endif
|
||||||
switch (Aex & 04177) {
|
switch (Aex & 04177) {
|
||||||
case 0:
|
case 0:
|
||||||
/* Точно неизвестно, что это такое, но драйвер МД
|
/*
|
||||||
* иногда выдает команду "увв 0". */
|
* Using an I/O control instruction with Aex == 0
|
||||||
|
* after issuing a 033 instruction with a non-zero Aex
|
||||||
|
* to send data to a device was required
|
||||||
|
* for some devices (e.g. printers) according to the docs.
|
||||||
|
* What is the exact purpose is unclear (timing, power, ???)
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
case 1: case 2:
|
case 1: case 2:
|
||||||
/* Управление обменом с магнитными барабанами */
|
/* Управление обменом с магнитными барабанами */
|
||||||
|
@ -562,7 +577,7 @@ static void cmd_033 ()
|
||||||
tty_send ((uint32) ACC & BITS(24));
|
tty_send ((uint32) ACC & BITS(24));
|
||||||
break;
|
break;
|
||||||
case 0141:
|
case 0141:
|
||||||
/* TODO: управление разметкой магнитной ленты */
|
/* TODO: formatting magnetic tape */
|
||||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||||
break;
|
break;
|
||||||
case 0142:
|
case 0142:
|
||||||
|
@ -570,11 +585,12 @@ static void cmd_033 ()
|
||||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||||
break;
|
break;
|
||||||
case 0147:
|
case 0147:
|
||||||
/* Запись в регистр управления электропитанием, */
|
/* Writing to the power supply control register
|
||||||
/* не оказывает видимого эффекта на выполнение */
|
* does not have any observable effect
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
case 0150: case 0151:
|
case 0150: case 0151:
|
||||||
/* TODO: управление вводом с перфокарт */
|
/* TODO: reading from punchcards */
|
||||||
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
longjmp (cpu_halt, STOP_UNIMPLEMENTED);
|
||||||
break;
|
break;
|
||||||
case 0153:
|
case 0153:
|
||||||
|
@ -727,10 +743,9 @@ void check_initial_setup ()
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((memory[TAKEN] & SETUP_REQS_ENABLED) == 0 ||
|
if ((memory[TAKEN] & SETUP_REQS_ENABLED) == 0 || /* not ready for setup */
|
||||||
(memory[TAKEN] & ALL_REQS_ENABLED) != 0 ||
|
(memory[TAKEN] & ALL_REQS_ENABLED) != 0 || /* all done */
|
||||||
(MGRP & GRP_PANEL_REQ) == 0) {
|
(MGRP & GRP_PANEL_REQ) == 0) { /* not at the moment */
|
||||||
/* Слишком рано, или уже не надо, или невовремя */
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,7 +789,7 @@ void check_initial_setup ()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute one instruction, placed on address PC:RUU_RIGHT_INSTR.
|
* Execute one instruction, placed on address PC:RUU_RIGHT_INSTR.
|
||||||
* Increment delay. When stopped, perform a longjmp to cpu_halt,
|
* When stopped, perform a longjmp to cpu_halt,
|
||||||
* sending a stop code.
|
* sending a stop code.
|
||||||
*/
|
*/
|
||||||
void cpu_one_inst ()
|
void cpu_one_inst ()
|
||||||
|
@ -782,6 +797,14 @@ void cpu_one_inst ()
|
||||||
int reg, opcode, addr, nextpc, next_mod;
|
int reg, opcode, addr, nextpc, next_mod;
|
||||||
t_value word;
|
t_value word;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instruction execution time in 100 ns ticks; not really used
|
||||||
|
* as the amortized 1 MIPS instruction rate is assumed.
|
||||||
|
* The assignments of MEAN_TIME(x,y) to the delay variable
|
||||||
|
* are kept as a reference.
|
||||||
|
*/
|
||||||
|
uint32 delay;
|
||||||
|
|
||||||
corr_stack = 0;
|
corr_stack = 0;
|
||||||
word = mmu_fetch (PC);
|
word = mmu_fetch (PC);
|
||||||
if (RUU & RUU_RIGHT_INSTR)
|
if (RUU & RUU_RIGHT_INSTR)
|
||||||
|
@ -1668,7 +1691,11 @@ t_stat sim_instr (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PC > BITS(15)) { /* выход за пределы памяти */
|
if (PC > BITS(15) && IS_SUPERVISOR(RUU)) {
|
||||||
|
/*
|
||||||
|
* Runaway instruction execution in supervisor mode
|
||||||
|
* warrants attention.
|
||||||
|
*/
|
||||||
besm6_draw_panel();
|
besm6_draw_panel();
|
||||||
return STOP_RUNOUT; /* stop simulation */
|
return STOP_RUNOUT; /* stop simulation */
|
||||||
}
|
}
|
||||||
|
@ -1680,7 +1707,8 @@ t_stat sim_instr (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PRP & MPRP) {
|
if (PRP & MPRP) {
|
||||||
/* регистр хранящий, сбрасывается программно */
|
/* There are interrupts pending in the peripheral
|
||||||
|
* interrupt register */
|
||||||
GRP |= GRP_SLAVE;
|
GRP |= GRP_SLAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1701,8 +1729,10 @@ t_stat sim_instr (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* В 9-й части частота таймера 250 Гц (4 мс),
|
* A 250 Hz clock as per the original documentation,
|
||||||
* в жизни - 50 Гц (20 мс).
|
* and matching the available software binaries.
|
||||||
|
* Some installations used 50 Hz with a modified OS
|
||||||
|
* for a better user time/system time ratio.
|
||||||
*/
|
*/
|
||||||
t_stat fast_clk (UNIT * this)
|
t_stat fast_clk (UNIT * this)
|
||||||
{
|
{
|
||||||
|
@ -1712,18 +1742,17 @@ t_stat fast_clk (UNIT * this)
|
||||||
++counter;
|
++counter;
|
||||||
++tty_counter;
|
++tty_counter;
|
||||||
|
|
||||||
/*besm6_debug ("*** таймер 20 мсек");*/
|
|
||||||
GRP |= GRP_TIMER;
|
GRP |= GRP_TIMER;
|
||||||
|
|
||||||
/* Медленный таймер: должен быть 16 Гц.
|
if ((counter & 15) == 0) {
|
||||||
* Но от него почему-то зависит вывод на терминалы,
|
/*
|
||||||
* поэтому ускорим. */
|
* The OS used the (undocumented, later addition) slow clock interrupt to initiate servicing
|
||||||
if ((counter & 3) == 0) {
|
* terminal I/O. Its frequency was reportedly 16 Hz; 64 ms is a good enough approximation.
|
||||||
/*besm6_debug ("*** таймер 80 мсек");*/
|
*/
|
||||||
GRP |= GRP_SLOW_CLK;
|
GRP |= GRP_SLOW_CLK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Перерисовка панели каждые 64 миллисекунды. */
|
/* Requesting panel redraw every 64 ms. */
|
||||||
if ((counter & 15) == 0) {
|
if ((counter & 15) == 0) {
|
||||||
redraw_panel = 1;
|
redraw_panel = 1;
|
||||||
}
|
}
|
||||||
|
@ -1741,7 +1770,7 @@ t_stat fast_clk (UNIT * this)
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT clocks[] = {
|
UNIT clocks[] = {
|
||||||
{ UDATA(fast_clk, UNIT_IDLE, 0), CLK_DELAY }, /* 40 р, 50 Гц */
|
{ UDATA(fast_clk, UNIT_IDLE, 0), CLK_DELAY }, /* Bit 40 of the GRP, 250 Hz */
|
||||||
};
|
};
|
||||||
|
|
||||||
t_stat clk_reset (DEVICE * dev)
|
t_stat clk_reset (DEVICE * dev)
|
||||||
|
|
|
@ -114,19 +114,15 @@ enum {
|
||||||
((x) >> 48) == CONVOL_NUMBER)
|
((x) >> 48) == CONVOL_NUMBER)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Вычисление правдоподобного времени выполнения команды,
|
* An attempt to approximate instruction execution times.
|
||||||
* зная количество тактов в УУ и среднее в АУ.
|
* The arguments number of clock ticks spent on an instruction
|
||||||
* Предполагаем, что в 50% случаев происходит совмещение
|
* in the ALU and in the CU; the computed result assumes
|
||||||
* выполнения, поэтому суммируем большее и половину
|
* a 50% overlap in execution.
|
||||||
* от меньшего значения.
|
|
||||||
*/
|
*/
|
||||||
#define MEAN_TIME(x,y) (x>y ? x+y/2 : x/2+y)
|
#define MEAN_TIME(x,y) (x>y ? x+y/2 : x/2+y)
|
||||||
|
|
||||||
/*
|
#define USEC 1 /* 1 microsecond */
|
||||||
* Считаем, что моделируеммая машина имеет опорную частоту 10 МГц.
|
#define MSEC (1000*USEC) /* 1 millisecond */
|
||||||
*/
|
|
||||||
#define USEC 1 /* одна микросекунда - десять тактов */
|
|
||||||
#define MSEC (1000*USEC) /* одна миллисекунда */
|
|
||||||
#define CLK_TPS 250 /* Fast Clock Ticks Per Second (every 4ms) */
|
#define CLK_TPS 250 /* Fast Clock Ticks Per Second (every 4ms) */
|
||||||
#define CLK_DELAY 4000 /* Uncalibrated instructions per clock tick */
|
#define CLK_DELAY 4000 /* Uncalibrated instructions per clock tick */
|
||||||
|
|
||||||
|
@ -135,6 +131,7 @@ extern UNIT tty_unit[];
|
||||||
extern UNIT clocks[];
|
extern UNIT clocks[];
|
||||||
extern t_value memory [MEMSIZE];
|
extern t_value memory [MEMSIZE];
|
||||||
extern t_value pult [8];
|
extern t_value pult [8];
|
||||||
|
|
||||||
extern uint32 PC, RAU, RUU;
|
extern uint32 PC, RAU, RUU;
|
||||||
extern uint32 M[NREGS];
|
extern uint32 M[NREGS];
|
||||||
extern t_value BRZ[8], RP[8], GRP, MGRP;
|
extern t_value BRZ[8], RP[8], GRP, MGRP;
|
||||||
|
@ -379,14 +376,15 @@ t_value besm6_pack (t_value val, t_value mask);
|
||||||
t_value besm6_unpack (t_value val, t_value mask);
|
t_value besm6_unpack (t_value val, t_value mask);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Разряды главного регистра прерываний (ГРП)
|
* Bits of the main interrupt register ГРП (GRP)
|
||||||
* Внешние:
|
* External:
|
||||||
*/
|
*/
|
||||||
#define GRP_PRN1_SYNC 04000000000000000LL /* 48 */
|
#define GRP_PRN1_SYNC 04000000000000000LL /* 48 */
|
||||||
#define GRP_PRN2_SYNC 02000000000000000LL /* 47 */
|
#define GRP_PRN2_SYNC 02000000000000000LL /* 47 */
|
||||||
#define GRP_DRUM1_FREE 01000000000000000LL /* 46 */
|
#define GRP_DRUM1_FREE 01000000000000000LL /* 46 */
|
||||||
#define GRP_DRUM2_FREE 00400000000000000LL /* 45 */
|
#define GRP_DRUM2_FREE 00400000000000000LL /* 45 */
|
||||||
#define GRP_VNIIEM 00300000000000000LL /* 44-43, placeholder */
|
#define GRP_UVVK1_SYNC 00200000000000000LL /* 44 */
|
||||||
|
#define GRP_UVVK2_SYNC 00100000000000000LL /* 43 */
|
||||||
#define GRP_FS1_SYNC 00040000000000000LL /* 42 */
|
#define GRP_FS1_SYNC 00040000000000000LL /* 42 */
|
||||||
#define GRP_FS2_SYNC 00020000000000000LL /* 41 */
|
#define GRP_FS2_SYNC 00020000000000000LL /* 41 */
|
||||||
#define GRP_TIMER 00010000000000000LL /* 40 */
|
#define GRP_TIMER 00010000000000000LL /* 40 */
|
||||||
|
@ -405,10 +403,10 @@ t_value besm6_unpack (t_value val, t_value mask);
|
||||||
#define GRP_CHAN5_FREE 00000000400000000LL /* 27 */
|
#define GRP_CHAN5_FREE 00000000400000000LL /* 27 */
|
||||||
#define GRP_CHAN6_FREE 00000000200000000LL /* 26 */
|
#define GRP_CHAN6_FREE 00000000200000000LL /* 26 */
|
||||||
#define GRP_CHAN7_FREE 00000000100000000LL /* 25 */
|
#define GRP_CHAN7_FREE 00000000100000000LL /* 25 */
|
||||||
#define GRP_SERIAL 00000000001000000LL /* 19 */
|
#define GRP_SERIAL 00000000001000000LL /* 19, nonstandard */
|
||||||
#define GRP_WATCHDOG 00000000000002000LL /* 11 */
|
#define GRP_WATCHDOG 00000000000002000LL /* 11 */
|
||||||
#define GRP_SLOW_CLK 00000000000001000LL /* 10 */
|
#define GRP_SLOW_CLK 00000000000001000LL /* 10, nonstandard */
|
||||||
/* Внутренние: */
|
/* Internal: */
|
||||||
#define GRP_DIVZERO 00000000034000000LL /* 23-21 */
|
#define GRP_DIVZERO 00000000034000000LL /* 23-21 */
|
||||||
#define GRP_OVERFLOW 00000000014000000LL /* 22-21 */
|
#define GRP_OVERFLOW 00000000014000000LL /* 22-21 */
|
||||||
#define GRP_CHECK 00000000004000000LL /* 21 */
|
#define GRP_CHECK 00000000004000000LL /* 21 */
|
||||||
|
@ -426,6 +424,23 @@ t_value besm6_unpack (t_value val, t_value mask);
|
||||||
#define GRP_SET_BLOCK(x,m) (((x) & ~GRP_BLOCK_MASK) | ((m) & GRP_BLOCK_MASK))
|
#define GRP_SET_BLOCK(x,m) (((x) & ~GRP_BLOCK_MASK) | ((m) & GRP_BLOCK_MASK))
|
||||||
#define GRP_SET_PAGE(x,m) (((x) & ~GRP_PAGE_MASK) | (((m)<<4) & GRP_PAGE_MASK))
|
#define GRP_SET_PAGE(x,m) (((x) & ~GRP_PAGE_MASK) | (((m)<<4) & GRP_PAGE_MASK))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bits of the peripheral interrupt register ПРП (PRP)
|
||||||
|
*/
|
||||||
|
#define PRP_UVVK1_END 010000000 /* 22 */
|
||||||
|
#define PRP_UVVK2_END 004000000 /* 21 */
|
||||||
|
#define PRP_PCARD1_CHECK 002000000 /* 20 */
|
||||||
|
#define PRP_PCARD2_CHECK 001000000 /* 19 */
|
||||||
|
#define PRP_PCARD1_PUNCH 000400000 /* 18 */
|
||||||
|
#define PRP_PCARD2_PUNCH 000200000 /* 17 */
|
||||||
|
#define PRP_PTAPE1_PUNCH 000100000 /* 16 */
|
||||||
|
#define PRP_PTAPE2_PUNCH 000040000 /* 15 */
|
||||||
|
/* 14-13 unused */
|
||||||
|
#define PRP_CONS1_INPUT 000004000 /* 12 */
|
||||||
|
#define PRP_CONS2_INPUT 000002000 /* 11 */
|
||||||
|
#define PRP_CONS1_DONE 000001000 /* 10 */
|
||||||
|
#define PRP_CONS2_DONE 000000400 /* 9 */
|
||||||
|
|
||||||
/* Номер блока ОЗУ или номер страницы, вызвавших прерывание */
|
/* Номер блока ОЗУ или номер страницы, вызвавших прерывание */
|
||||||
extern uint32 iintr_data;
|
extern uint32 iintr_data;
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ DEVICE fs_dev = {
|
||||||
enum {
|
enum {
|
||||||
FS_IDLE,
|
FS_IDLE,
|
||||||
FS_STARTING,
|
FS_STARTING,
|
||||||
|
FS_BINARY,
|
||||||
FS_RUNNING,
|
FS_RUNNING,
|
||||||
FS_IMAGE,
|
FS_IMAGE,
|
||||||
FS_IMAGE_LAST = FS_IMAGE + CARD_LEN - 1,
|
FS_IMAGE_LAST = FS_IMAGE + CARD_LEN - 1,
|
||||||
|
@ -100,6 +101,8 @@ enum {
|
||||||
FS_TAIL,
|
FS_TAIL,
|
||||||
} fs_state[2];
|
} fs_state[2];
|
||||||
|
|
||||||
|
int fs_textmode[2];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset routine
|
* Reset routine
|
||||||
*/
|
*/
|
||||||
|
@ -116,10 +119,16 @@ t_stat fs_reset (DEVICE *dptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attaches a raw binary file by default,
|
||||||
|
* with a -t switch attaches a prepared text file in UTF-8.
|
||||||
|
*/
|
||||||
t_stat fs_attach (UNIT *u, char *cptr)
|
t_stat fs_attach (UNIT *u, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat s;
|
t_stat s;
|
||||||
int num = u - fs_unit;
|
int num = u - fs_unit;
|
||||||
|
fs_textmode[num] = sim_switches & SWMASK('T');
|
||||||
|
sim_switches &= ~SWMASK('T');
|
||||||
s = attach_unit (u, cptr);
|
s = attach_unit (u, cptr);
|
||||||
if (s != SCPE_OK)
|
if (s != SCPE_OK)
|
||||||
return s;
|
return s;
|
||||||
|
@ -186,6 +195,20 @@ void fs_control (int num, uint32 cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char unicode_to_gost (unsigned short val);
|
unsigned char unicode_to_gost (unsigned short val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The UPP code is the GOST 10859 code with odd parity.
|
||||||
|
* UPP stood for "unit for preparation of punchards".
|
||||||
|
*/
|
||||||
|
static unsigned char unicode_to_upp (unsigned short ch) {
|
||||||
|
unsigned char ret;
|
||||||
|
ch = ret = unicode_to_gost (ch);
|
||||||
|
ch = (ch & 0x55) + ((ch >> 1) & 0x55);
|
||||||
|
ch = (ch & 0x33) + ((ch >> 2) & 0x33);
|
||||||
|
ch = (ch & 0x0F) + ((ch >> 4) & 0x0F);
|
||||||
|
return (ch & 1) ? ret : ret | 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
static int utf8_getc (FILE *fin);
|
static int utf8_getc (FILE *fin);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -194,64 +217,66 @@ static int utf8_getc (FILE *fin);
|
||||||
*/
|
*/
|
||||||
t_stat fs_event (UNIT *u)
|
t_stat fs_event (UNIT *u)
|
||||||
{
|
{
|
||||||
|
static int cnt;
|
||||||
int num = u - fs_unit;
|
int num = u - fs_unit;
|
||||||
again:
|
again:
|
||||||
if (fs_state[num] == FS_STARTING) {
|
if (fs_state[num] == FS_STARTING) {
|
||||||
/* По первому прерыванию после запуска двигателя ничего не читаем */
|
/* The first interrupt after starting the motor is dummy,
|
||||||
|
* no need to read anything from the attached file.
|
||||||
|
*/
|
||||||
FS[num] = 0;
|
FS[num] = 0;
|
||||||
fs_state[num] = FS_RUNNING;
|
cnt = 0;
|
||||||
} else if (fs_state[num] == FS_RUNNING) {
|
fs_state[num] = fs_textmode[num] ? FS_RUNNING : FS_BINARY;
|
||||||
int ch;
|
} else if (fs_state[num] == FS_BINARY) {
|
||||||
/* переводы строк игнорируются */
|
int ch = getc (u->fileref);
|
||||||
while ((ch = utf8_getc (u->fileref)) == '\n');
|
|
||||||
if (ch < 0) {
|
if (ch < 0) {
|
||||||
/* хвост ленты без пробивок */
|
|
||||||
FS[num] = 0;
|
FS[num] = 0;
|
||||||
fs_state[num] = FS_TAIL;
|
fs_state[num] = FS_TAIL;
|
||||||
} else if (ch == '\f') {
|
} else {
|
||||||
|
FS[num] = ch;
|
||||||
|
}
|
||||||
|
} else if (fs_state[num] == FS_RUNNING) {
|
||||||
|
int ch;
|
||||||
|
/* Line separators are ignored in running text mode */
|
||||||
|
do ch = utf8_getc (u->fileref); while (ch == '\n' || ch == '\r');
|
||||||
|
if (ch < 0) {
|
||||||
|
/* the tail end of the tape has no holes */
|
||||||
|
FS[num] = 0;
|
||||||
|
fs_state[num] = FS_TAIL;
|
||||||
|
} else if (ch == (']' & 037)) {
|
||||||
|
/* Switching from running text mode to "virtual punchcard" mode and back
|
||||||
|
* is done with an ASCII GS (group separator) symbol ctrl-].
|
||||||
|
*/
|
||||||
fs_state[num] = FS_IMAGE;
|
fs_state[num] = FS_IMAGE;
|
||||||
goto again;
|
goto again;
|
||||||
} else {
|
} else {
|
||||||
ch = FS[num] = unicode_to_gost (ch);
|
FS[num] = unicode_to_upp (ch);
|
||||||
ch = (ch & 0x55) + ((ch >> 1) & 0x55);
|
|
||||||
ch = (ch & 0x33) + ((ch >> 2) & 0x33);
|
|
||||||
ch = (ch & 0x0F) + ((ch >> 4) & 0x0F);
|
|
||||||
if (ch & 1); else FS[num] |= 0x80;
|
|
||||||
}
|
}
|
||||||
} else if (FS_IMAGE <= fs_state[num] && fs_state[num] <= FS_IMAGE_LAST) {
|
} else if (FS_IMAGE <= fs_state[num] && fs_state[num] <= FS_IMAGE_LAST) {
|
||||||
int ch = utf8_getc (u->fileref);
|
int ch = utf8_getc (u->fileref);
|
||||||
if (ch < 0) {
|
if (ch < 0) {
|
||||||
/* обрыв ленты */
|
/* premature end of tape */
|
||||||
FS[num] = 0;
|
FS[num] = 0;
|
||||||
fs_state[num] = FS_TAIL;
|
fs_state[num] = FS_TAIL;
|
||||||
|
} else if (ch == '\r') {
|
||||||
|
/* always ignored */
|
||||||
|
goto again;
|
||||||
} else if (ch == '\n') {
|
} else if (ch == '\n') {
|
||||||
/* идем дополнять образ карты нулевыми байтами */
|
/* Start returning zero bytes up to the end of the current "virtual punchard" */
|
||||||
fs_state[num] = FS_FILLUP + (fs_state[num] - FS_IMAGE);
|
fs_state[num] = FS_FILLUP + (fs_state[num] - FS_IMAGE);
|
||||||
goto again;
|
goto again;
|
||||||
} else if (ch == '\f') {
|
} else if (ch == (']' & 037)) {
|
||||||
if (fs_state[num] != FS_IMAGE)
|
if (fs_state[num] != FS_IMAGE)
|
||||||
besm6_debug("<<< ENDA3 requested mid-card?");
|
besm6_debug("<<< ENDA3 requested mid-card?");
|
||||||
fs_state[num] = FS_ENDA3;
|
fs_state[num] = FS_ENDA3;
|
||||||
goto again;
|
goto again;
|
||||||
} else {
|
} else {
|
||||||
ch = FS[num] = unicode_to_gost (ch);
|
FS[num] = unicode_to_upp (ch);
|
||||||
ch = (ch & 0x55) + ((ch >> 1) & 0x55);
|
if (++fs_state[num] == FS_TOOLONG) {
|
||||||
ch = (ch & 0x33) + ((ch >> 2) & 0x33);
|
/* If a line is too long (> 120 chars), start the next "virtual punchcard" */
|
||||||
ch = (ch & 0x0F) + ((ch >> 4) & 0x0F);
|
fs_state[num] = FS_IMAGE;
|
||||||
if (ch & 1); else FS[num] |= 0x80;
|
}
|
||||||
++fs_state[num];
|
|
||||||
}
|
}
|
||||||
} else if (fs_state[num] == FS_TOOLONG) {
|
|
||||||
/* дочитываем до конца строки */
|
|
||||||
int ch;
|
|
||||||
besm6_debug("<<< too long???");
|
|
||||||
while ((ch = utf8_getc (u->fileref)) != '\n' && ch >= 0);
|
|
||||||
if (ch < 0) {
|
|
||||||
/* хвост ленты без пробивок */
|
|
||||||
FS[num] = 0;
|
|
||||||
fs_state[num] = FS_TAIL;
|
|
||||||
} else
|
|
||||||
goto again;
|
|
||||||
} else if (FS_FILLUP <= fs_state[num] && fs_state[num] <= FS_FILLUP_LAST) {
|
} else if (FS_FILLUP <= fs_state[num] && fs_state[num] <= FS_FILLUP_LAST) {
|
||||||
FS[num] = 0;
|
FS[num] = 0;
|
||||||
if (++fs_state[num] == FS_ENDA3) {
|
if (++fs_state[num] == FS_ENDA3) {
|
||||||
|
@ -278,15 +303,21 @@ int fs_read(int num) {
|
||||||
|
|
||||||
return FS[num];
|
return FS[num];
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Unlike the OS which uses GOST overline (approximated by ^) as a line separator
|
||||||
|
* in running text mode, the BESM-ALGOL programming system used a nonprintable
|
||||||
|
* character (0174) from the unused part of the codetable to allow compressing multiple
|
||||||
|
* source lines on a punchcard. To specify that character,
|
||||||
|
* we use ASCII RS (record separator) symbol ctrl-^.
|
||||||
|
*/
|
||||||
unsigned char
|
unsigned char
|
||||||
unicode_to_gost (unsigned short val)
|
unicode_to_gost (unsigned short val)
|
||||||
{
|
{
|
||||||
static const unsigned char tab0 [256] = {
|
static const unsigned char tab0 [256] = {
|
||||||
/* 00 - 07 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
/* 00 - 07 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
/* 08 - 0f */ 017, 017, 0214, 017, 017, 0174, 017, 017,
|
/* 08 - 0f */ 017, 017, 0214, 017, 017, 017, 017, 017,
|
||||||
/* 10 - 17 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
/* 10 - 17 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
/* 18 - 1f */ 017, 017, 017, 017, 017, 017, 017, 017,
|
/* 18 - 1f */ 017, 017, 017, 017, 017, 017, 0174, 017,
|
||||||
/* !"#$%&' */ 0017, 0133, 0134, 0034, 0127, 0126, 0121, 0033,
|
/* !"#$%&' */ 0017, 0133, 0134, 0034, 0127, 0126, 0121, 0033,
|
||||||
/* ()*+,-./ */ 0022, 0023, 0031, 0012, 0015, 0013, 0016, 0014,
|
/* ()*+,-./ */ 0022, 0023, 0031, 0012, 0015, 0013, 0016, 0014,
|
||||||
/* 01234567 */ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
|
/* 01234567 */ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
|
||||||
|
@ -413,6 +444,11 @@ unicode_to_gost (unsigned short val)
|
||||||
case 0x83: return 0122;
|
case 0x83: return 0122;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x23:
|
||||||
|
switch ((unsigned char) val) {
|
||||||
|
case 0xe8: return 0020;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0x25:
|
case 0x25:
|
||||||
switch ((unsigned char) val) {
|
switch ((unsigned char) val) {
|
||||||
case 0xc7: return 0127;
|
case 0xc7: return 0127;
|
||||||
|
|
|
@ -97,6 +97,8 @@ t_stat vt_clk(UNIT *);
|
||||||
extern char *get_sim_sw (char *cptr);
|
extern char *get_sim_sw (char *cptr);
|
||||||
extern int32 tmr_poll; /* calibrated clock timer poll */
|
extern int32 tmr_poll; /* calibrated clock timer poll */
|
||||||
|
|
||||||
|
int attached_console;
|
||||||
|
|
||||||
UNIT tty_unit [] = {
|
UNIT tty_unit [] = {
|
||||||
{ UDATA (vt_clk, UNIT_DIS|UNIT_IDLE, 0) }, /* fake unit, clock */
|
{ UDATA (vt_clk, UNIT_DIS|UNIT_IDLE, 0) }, /* fake unit, clock */
|
||||||
{ UDATA (NULL, UNIT_SEQ, 0) },
|
{ UDATA (NULL, UNIT_SEQ, 0) },
|
||||||
|
@ -228,6 +230,19 @@ t_stat vt_clk (UNIT * this)
|
||||||
t->rxb [t->rxbpi++] = '\3';
|
t->rxb [t->rxbpi++] = '\3';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It the operator console is remote, we still need to probe the local keyboard
|
||||||
|
* for a WRU, say, 10 times a second.
|
||||||
|
*/
|
||||||
|
if (!attached_console) {
|
||||||
|
static int divider;
|
||||||
|
if (++divider == CLK_TPS/10) {
|
||||||
|
divider == 0;
|
||||||
|
if (SCPE_STOP == sim_poll_kbd())
|
||||||
|
stop_cpu = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Polling sockets for transmission. */
|
/* Polling sockets for transmission. */
|
||||||
tmxr_poll_tx (&tty_desc);
|
tmxr_poll_tx (&tty_desc);
|
||||||
/* If the TTY system is not idle, schedule the next interrupt
|
/* If the TTY system is not idle, schedule the next interrupt
|
||||||
|
@ -343,6 +358,7 @@ t_stat tty_attach (UNIT *u, char *cptr)
|
||||||
if (num <= TTY_MAX)
|
if (num <= TTY_MAX)
|
||||||
vt_mask |= 1 << (TTY_MAX - num);
|
vt_mask |= 1 << (TTY_MAX - num);
|
||||||
besm6_debug ("*** console on T%03o", num);
|
besm6_debug ("*** console on T%03o", num);
|
||||||
|
attached_console = 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
return SCPE_ALATT;
|
return SCPE_ALATT;
|
||||||
|
|
|
@ -7,18 +7,18 @@ set cpu idle
|
||||||
;set disk debug
|
;set disk debug
|
||||||
|
|
||||||
;
|
;
|
||||||
; Приводим барабаны в исходное состояние.
|
; Initializing the magnetic drums.
|
||||||
;
|
;
|
||||||
attach -n drum0 drum1x.bin
|
attach -n drum0 drum1x.bin
|
||||||
attach -n drum1 drum2x.bin
|
attach -n drum1 drum2x.bin
|
||||||
|
|
||||||
;
|
;
|
||||||
; Создаем рабочий диск.
|
; Initializing a scratch disk.
|
||||||
;
|
;
|
||||||
attach -n disk6 2052.bin
|
attach -n disk6 2052.bin
|
||||||
|
|
||||||
;
|
;
|
||||||
; Подключаем диски.
|
; Attaching system disks.
|
||||||
;
|
;
|
||||||
attach -e disk7 sbor2053.bin
|
attach -e disk7 sbor2053.bin
|
||||||
attach -e disk5 krab2063.bin
|
attach -e disk5 krab2063.bin
|
||||||
|
@ -27,27 +27,47 @@ attach -e disk1 svs2048.bin
|
||||||
attach -e disk2 alt2048.bin
|
attach -e disk2 alt2048.bin
|
||||||
|
|
||||||
;
|
;
|
||||||
; Подключаем АЦПУ.
|
; Attaching an output file.
|
||||||
;
|
;
|
||||||
attach prn0 output.txt
|
attach -n prn0 output.txt
|
||||||
|
|
||||||
;
|
;
|
||||||
; Активируем операторский терминал,
|
; Allowing telnet connections, port 4199.
|
||||||
; на который идут сообщения.
|
|
||||||
;
|
;
|
||||||
|
attach tty 4199
|
||||||
|
|
||||||
|
;
|
||||||
|
; Attaching a terminal serving as the operator console.
|
||||||
|
;
|
||||||
|
; This works on UNIX-like systems.
|
||||||
attach tty1 console
|
attach tty1 console
|
||||||
|
|
||||||
|
; On Windows, a UTF-8 connnection works better over telnet.
|
||||||
|
; Use a different port for the operator console just in case.
|
||||||
|
;attach tty Line=1,4198
|
||||||
|
;set env PATH %PATH%;C:\Program Files (x86)\PuTTY
|
||||||
|
;! start putty telnet://localhost:4198
|
||||||
;
|
;
|
||||||
; Режимы по вкусу
|
; On Unix, telnet can also be used for the operator console.
|
||||||
|
; ! gnome-terminal -x sh -c "telnet localhost 4198" &
|
||||||
;
|
;
|
||||||
|
; Terminal modes (how to enter Cyrillics, should the backspace be erasing), etc.
|
||||||
|
; (authbs == authentic non-erasing)
|
||||||
|
;
|
||||||
|
; Using UTF-8 for input
|
||||||
|
; set tty1 unicode,authbs
|
||||||
|
;
|
||||||
|
; Entering Russian letters as lowercase Latin letters
|
||||||
|
; according to the standard Russian layout
|
||||||
;set tty1 jcuken,authbs
|
;set tty1 jcuken,authbs
|
||||||
|
;
|
||||||
|
; Entering Russian letters as corresponding lowercase Latin letters.
|
||||||
|
; Q = "ya", W = "ve", Y = "yeru", J = "short I", X = "soft sign",
|
||||||
|
; C = "ts", V = "zhe", grave = "yu", tilde = "ch", { = "sh", } = "shch",
|
||||||
|
; | = "reverse e"
|
||||||
set tty1 qwerty,authbs
|
set tty1 qwerty,authbs
|
||||||
set -n tty1 log=tty1.txt
|
set -n tty1 log=tty1.txt
|
||||||
|
|
||||||
;
|
|
||||||
; Разрешаем подключение пользователей по telnet, порт 4199.
|
|
||||||
;
|
|
||||||
attach tty 4199
|
|
||||||
set tty2 authbs
|
set tty2 authbs
|
||||||
set tty3 authbs
|
set tty3 authbs
|
||||||
set tty4 authbs
|
set tty4 authbs
|
||||||
|
@ -73,18 +93,30 @@ set tty23 authbs
|
||||||
set tty24 authbs
|
set tty24 authbs
|
||||||
|
|
||||||
;
|
;
|
||||||
; Включение БРС/БРЗ для совместимости.
|
; Enabling the true LRU behavior of caches
|
||||||
; Замедляет работу на 20%.
|
; slows down the simulation speed ~20%
|
||||||
;
|
;
|
||||||
;set mmu cache
|
;set mmu cache
|
||||||
|
|
||||||
|
echo ###
|
||||||
|
echo ### Zeroing out the first page of RAM (as would be entered from
|
||||||
|
echo ### switch registers after powering up the machine,
|
||||||
|
echo ### likely about once a year or less).
|
||||||
|
echo ###
|
||||||
|
|
||||||
|
d -ml 1 xta, vtm 1777(1)
|
||||||
|
d -ml 2 atx (1), utm -1(1)
|
||||||
|
d -ml 3 v1m 2(1), stop
|
||||||
|
run 1
|
||||||
|
|
||||||
|
echo ###
|
||||||
|
echo ### Done; data cache registers are displayed above. An error message
|
||||||
|
echo ### would be usually displayed there after a STOP instruction.
|
||||||
|
echo ### Naturally, at the moment they all contain zeros. Booting the OS now...
|
||||||
|
echo ###
|
||||||
;
|
;
|
||||||
; Запуск ОС ДИСПАК.
|
; Booting OS DISPAK.
|
||||||
;
|
;
|
||||||
load boot_dispak.b6
|
load boot_dispak.b6
|
||||||
|
|
||||||
; Происходит контроль числа по адресу 1031
|
|
||||||
d 1031 0
|
|
||||||
|
|
||||||
run 2000
|
run 2000
|
||||||
;quit
|
;quit
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# Attaching the input device
|
# Attaching the input device
|
||||||
at fs0 input.txt
|
at -t fs0 input.txt
|
||||||
# Waiting for the end of initial setup
|
# Waiting for the end of initial setup
|
||||||
expect -r "ДATA.*\n"
|
expect -r "ДATA.*\n"
|
||||||
do dispak.ini
|
do dispak.ini
|
||||||
# Now we're ready to send commands from the front panel
|
# Now we're ready to send commands from the front panel
|
||||||
echo Requesting input from the punch tape reader (FS8)
|
echo Requesting input from the punch tape reader (FS8), it takes a few seconds
|
||||||
d 6 1
|
d 6 1
|
||||||
d 5 10
|
d 5 10
|
||||||
set cpu req
|
set cpu req
|
||||||
|
@ -14,6 +14,7 @@ go
|
||||||
# The process had been started, check state every 10 model seconds
|
# The process had been started, check state every 10 model seconds
|
||||||
send after=1000000 "WCPP\r"
|
send after=1000000 "WCPP\r"
|
||||||
expect -p -r "4199.*\n" send after=10000000 "WCPP\r"; go
|
expect -p -r "4199.*\n" send after=10000000 "WCPP\r"; go
|
||||||
|
expect -c "KЗ" step 10000000
|
||||||
expect -c "HET\r\n" step 10000
|
expect -c "HET\r\n" step 10000
|
||||||
go
|
go
|
||||||
echo Enabling the printer (ONL A0)
|
echo Enabling the printer (ONL A0)
|
||||||
|
@ -24,7 +25,7 @@ expect -r "ECT.*\n"
|
||||||
go
|
go
|
||||||
echo Checking for the printing to finish
|
echo Checking for the printing to finish
|
||||||
send "HOMB\r"
|
send "HOMB\r"
|
||||||
expect -p -r "4199.*\n" send "HOMB\r"; go
|
expect -p -r "A0.*\n" send "HOMB\r"; go
|
||||||
expect -c "HET\r\n"
|
expect -c "HET\r\n"
|
||||||
go
|
go
|
||||||
echo Done
|
echo Done
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
ШИФР 419999 ЗС5^
|
ШИФР 419999 ЗС5^
|
||||||
EEВ1А3
|
EEВ1А3
|
||||||
*NAME PRIME NUMBERS
|
*NAME PRIME NUMBERS
|
||||||
* The ^L char before *NAME is important
|
* The ^L char before *NAME is important
|
||||||
* NO LIST Disable source listing by removing spaces between * and NO
|
* NO LIST Disable source listing by removing spaces between * and NO
|
||||||
*NO LOAD LIST Enable loader listing by adding 5 spaces between * and NO
|
*NO LOAD LIST Enable loader listing by adding 5 spaces between * and NO
|
||||||
|
@ -50,4 +50,4 @@ c------ Printing every 1000th prime number
|
||||||
*EXECUTE
|
*EXECUTE
|
||||||
* The ^L char after *END FILE is important
|
* The ^L char after *END FILE is important
|
||||||
*END FILE
|
*END FILE
|
||||||
ЕКОНЕЦ
|
ЕКОНЕЦ
|
||||||
|
|
Loading…
Add table
Reference in a new issue