BESM6: Addition of BESM-6 Simulator written by Leo Broukhis and Serge Vakulenko
This commit is contained in:
commit
483a969837
23 changed files with 11284 additions and 2 deletions
483
BESM6/besm6_arith.c
Normal file
483
BESM6/besm6_arith.c
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
/*
|
||||||
|
* BESM-6 arithmetic instructions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1997-2009, Leonid Broukhis
|
||||||
|
* Copyright (c) 2009, Serge Vakulenko
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#include <math.h>
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
t_uint64 mantissa;
|
||||||
|
unsigned exponent; /* offset by 64 */
|
||||||
|
} alureg_t; /* ALU register type */
|
||||||
|
|
||||||
|
static alureg_t toalu (t_value val)
|
||||||
|
{
|
||||||
|
alureg_t ret;
|
||||||
|
|
||||||
|
ret.mantissa = val & BITS41;
|
||||||
|
ret.exponent = (val >> 41) & BITS(7);
|
||||||
|
if (ret.mantissa & BIT41)
|
||||||
|
ret.mantissa |= BIT42;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SIM_INLINE is_negative (alureg_t *word)
|
||||||
|
{
|
||||||
|
return (word->mantissa & BIT41) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void negate (alureg_t *val)
|
||||||
|
{
|
||||||
|
if (is_negative (val))
|
||||||
|
val->mantissa |= BIT42;
|
||||||
|
val->mantissa = (~val->mantissa + 1) & BITS42;
|
||||||
|
if (((val->mantissa >> 1) ^ val->mantissa) & BIT41) {
|
||||||
|
val->mantissa >>= 1;
|
||||||
|
++val->exponent;
|
||||||
|
}
|
||||||
|
if (is_negative (val))
|
||||||
|
val->mantissa |= BIT42;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 48-й разряд -> 1, 47-й -> 2 и т.п.
|
||||||
|
* Единица 1-го разряда и нулевое слово -> 48,
|
||||||
|
* как в первоначальном варианте системы команд.
|
||||||
|
*/
|
||||||
|
int besm6_highest_bit (t_value val)
|
||||||
|
{
|
||||||
|
int n = 32, cnt = 0;
|
||||||
|
do {
|
||||||
|
t_value tmp = val;
|
||||||
|
if (tmp >>= n) {
|
||||||
|
cnt += n;
|
||||||
|
val = tmp;
|
||||||
|
}
|
||||||
|
} while (n >>= 1);
|
||||||
|
return 48 - cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Нормализация и округление.
|
||||||
|
* Результат помещается в регистры ACC и 40-1 разряды RMR.
|
||||||
|
* 48-41 разряды RMR сохраняются.
|
||||||
|
*/
|
||||||
|
static void normalize_and_round (alureg_t acc, t_uint64 mr, int rnd_rq)
|
||||||
|
{
|
||||||
|
t_uint64 rr = 0;
|
||||||
|
int i;
|
||||||
|
t_uint64 r;
|
||||||
|
|
||||||
|
if (RAU & RAU_NORM_DISABLE)
|
||||||
|
goto chk_rnd;
|
||||||
|
i = (acc.mantissa >> 39) & 3;
|
||||||
|
if (i == 0) {
|
||||||
|
r = acc.mantissa & BITS40;
|
||||||
|
if (r) {
|
||||||
|
int cnt = besm6_highest_bit (r) - 9;
|
||||||
|
r <<= cnt;
|
||||||
|
rr = mr >> (40 - cnt);
|
||||||
|
acc.mantissa = r | rr;
|
||||||
|
mr <<= cnt;
|
||||||
|
acc.exponent -= cnt;
|
||||||
|
goto chk_zero;
|
||||||
|
}
|
||||||
|
r = mr & BITS40;
|
||||||
|
if (r) {
|
||||||
|
int cnt = besm6_highest_bit (r) - 9;
|
||||||
|
rr = mr;
|
||||||
|
r <<= cnt;
|
||||||
|
acc.mantissa = r;
|
||||||
|
mr = 0;
|
||||||
|
acc.exponent -= 40 + cnt;
|
||||||
|
goto chk_zero;
|
||||||
|
}
|
||||||
|
goto zero;
|
||||||
|
} else if (i == 3) {
|
||||||
|
r = ~acc.mantissa & BITS40;
|
||||||
|
if (r) {
|
||||||
|
int cnt = besm6_highest_bit (r) - 9;
|
||||||
|
r = (r << cnt) | ((1LL << cnt) - 1);
|
||||||
|
rr = mr >> (40 - cnt);
|
||||||
|
acc.mantissa = BIT41 | (~r & BITS40) | rr;
|
||||||
|
mr <<= cnt;
|
||||||
|
acc.exponent -= cnt;
|
||||||
|
goto chk_zero;
|
||||||
|
}
|
||||||
|
r = ~mr & BITS40;
|
||||||
|
if (r) {
|
||||||
|
int cnt = besm6_highest_bit (r) - 9;
|
||||||
|
rr = mr;
|
||||||
|
r = (r << cnt) | ((1LL << cnt) - 1);
|
||||||
|
acc.mantissa = BIT41 | (~r & BITS40);
|
||||||
|
mr = 0;
|
||||||
|
acc.exponent -= 40 + cnt;
|
||||||
|
goto chk_zero;
|
||||||
|
} else {
|
||||||
|
rr = 1;
|
||||||
|
acc.mantissa = BIT41;
|
||||||
|
mr = 0;
|
||||||
|
acc.exponent -= 80;
|
||||||
|
goto chk_zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chk_zero:
|
||||||
|
if (rr)
|
||||||
|
rnd_rq = 0;
|
||||||
|
chk_rnd:
|
||||||
|
if (acc.exponent & 0x8000)
|
||||||
|
goto zero;
|
||||||
|
if (! (RAU & RAU_ROUND_DISABLE) && rnd_rq)
|
||||||
|
acc.mantissa |= 1;
|
||||||
|
|
||||||
|
if (! acc.mantissa && ! (RAU & RAU_NORM_DISABLE)) {
|
||||||
|
zero: ACC = 0;
|
||||||
|
RMR &= ~BITS40;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACC = (t_value) (acc.exponent & BITS(7)) << 41 |
|
||||||
|
(acc.mantissa & BITS41);
|
||||||
|
RMR = (RMR & ~BITS40) | (mr & BITS40);
|
||||||
|
/* При переполнении мантисса и младшие разряды порядка верны */
|
||||||
|
if (acc.exponent & 0x80) {
|
||||||
|
if (! (RAU & RAU_OVF_DISABLE))
|
||||||
|
longjmp (cpu_halt, STOP_OVFL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Сложение и все варианты вычитаний.
|
||||||
|
* Исходные значения: регистр ACC и аргумент 'val'.
|
||||||
|
* Результат помещается в регистр ACC и 40-1 разряды RMR.
|
||||||
|
*/
|
||||||
|
void besm6_add (t_value val, int negate_acc, int negate_val)
|
||||||
|
{
|
||||||
|
t_uint64 mr;
|
||||||
|
alureg_t acc, word, a1, a2;
|
||||||
|
int diff, neg, rnd_rq = 0;
|
||||||
|
|
||||||
|
acc = toalu (ACC);
|
||||||
|
word = toalu (val);
|
||||||
|
if (! negate_acc) {
|
||||||
|
if (! negate_val) {
|
||||||
|
/* Сложение */
|
||||||
|
} else {
|
||||||
|
/* Вычитание */
|
||||||
|
negate (&word);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (! negate_val) {
|
||||||
|
/* Обратное вычитание */
|
||||||
|
negate (&acc);
|
||||||
|
} else {
|
||||||
|
/* Вычитание модулей */
|
||||||
|
if (is_negative (&acc))
|
||||||
|
negate (&acc);
|
||||||
|
if (! is_negative (&word))
|
||||||
|
negate (&word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff = acc.exponent - word.exponent;
|
||||||
|
if (diff < 0) {
|
||||||
|
diff = -diff;
|
||||||
|
a1 = acc;
|
||||||
|
a2 = word;
|
||||||
|
} else {
|
||||||
|
a1 = word;
|
||||||
|
a2 = acc;
|
||||||
|
}
|
||||||
|
mr = 0;
|
||||||
|
neg = is_negative (&a1);
|
||||||
|
if (diff == 0) {
|
||||||
|
/* Nothing to do. */
|
||||||
|
} else if (diff <= 40) {
|
||||||
|
rnd_rq = (mr = (a1.mantissa << (40 - diff)) & BITS40) != 0;
|
||||||
|
a1.mantissa = ((a1.mantissa >> diff) |
|
||||||
|
(neg ? (~0ll << (40 - diff)) : 0)) & BITS42;
|
||||||
|
} else if (diff <= 80) {
|
||||||
|
diff -= 40;
|
||||||
|
rnd_rq = a1.mantissa != 0;
|
||||||
|
mr = ((a1.mantissa >> diff) |
|
||||||
|
(neg ? (~0ll << (40 - diff)) : 0)) & BITS40;
|
||||||
|
if (neg) {
|
||||||
|
a1.mantissa = BITS42;
|
||||||
|
} else
|
||||||
|
a1.mantissa = 0;
|
||||||
|
} else {
|
||||||
|
rnd_rq = a1.mantissa != 0;
|
||||||
|
if (neg) {
|
||||||
|
mr = BITS40;
|
||||||
|
a1.mantissa = BITS42;
|
||||||
|
} else
|
||||||
|
mr = a1.mantissa = 0;
|
||||||
|
}
|
||||||
|
acc.exponent = a2.exponent;
|
||||||
|
acc.mantissa = a1.mantissa + a2.mantissa;
|
||||||
|
|
||||||
|
/* Если требуется нормализация вправо, биты 42:41
|
||||||
|
* принимают значение 01 или 10. */
|
||||||
|
switch ((acc.mantissa >> 40) & 3) {
|
||||||
|
case 2:
|
||||||
|
case 1:
|
||||||
|
rnd_rq |= acc.mantissa & 1;
|
||||||
|
mr = (mr >> 1) | ((acc.mantissa & 1) << 39);
|
||||||
|
acc.mantissa >>= 1;
|
||||||
|
++acc.exponent;
|
||||||
|
}
|
||||||
|
normalize_and_round (acc, mr, rnd_rq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* non-restoring division
|
||||||
|
*/
|
||||||
|
#define ABS(x) ((x) < 0 ? -x : x)
|
||||||
|
#define INT64(x) ((x) & BIT41 ? (-1LL << 40) | (x) : x)
|
||||||
|
static alureg_t nrdiv (alureg_t n, alureg_t d)
|
||||||
|
{
|
||||||
|
t_int64 nn, dd, q, res;
|
||||||
|
alureg_t quot;
|
||||||
|
|
||||||
|
/* to compensate for potential normalization to the right */
|
||||||
|
nn = INT64(n.mantissa)*2;
|
||||||
|
dd = INT64(d.mantissa)*2;
|
||||||
|
res = 0, q = BIT41;
|
||||||
|
|
||||||
|
if (ABS(nn) >= ABS(dd)) {
|
||||||
|
/* normalization to the right */
|
||||||
|
nn/=2;
|
||||||
|
n.exponent++;
|
||||||
|
}
|
||||||
|
while (q > 1) {
|
||||||
|
if (nn == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ABS(nn) < BIT40)
|
||||||
|
nn *= 2; /* magic shortcut */
|
||||||
|
else if ((nn > 0) ^ (dd > 0)) {
|
||||||
|
res -= q;
|
||||||
|
nn = 2*nn+dd;
|
||||||
|
} else {
|
||||||
|
res += q;
|
||||||
|
nn = 2*nn-dd;
|
||||||
|
}
|
||||||
|
q /= 2;
|
||||||
|
}
|
||||||
|
quot.mantissa = res/2;
|
||||||
|
quot.exponent = n.exponent-d.exponent+64;
|
||||||
|
return quot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Деление.
|
||||||
|
* Исходные значения: регистр ACC и аргумент 'val'.
|
||||||
|
* Результат помещается в регистр ACC, содержимое RMR не определено.
|
||||||
|
*/
|
||||||
|
void besm6_divide (t_value val)
|
||||||
|
{
|
||||||
|
alureg_t acc;
|
||||||
|
alureg_t dividend, divisor;
|
||||||
|
|
||||||
|
if (((val ^ (val << 1)) & BIT41) == 0) {
|
||||||
|
/* Ненормализованный делитель: деление на ноль. */
|
||||||
|
longjmp (cpu_halt, STOP_DIVZERO);
|
||||||
|
}
|
||||||
|
dividend = toalu(ACC);
|
||||||
|
divisor = toalu(val);
|
||||||
|
|
||||||
|
acc = nrdiv(dividend, divisor);
|
||||||
|
|
||||||
|
normalize_and_round (acc, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Умножение.
|
||||||
|
* Исходные значения: регистр ACC и аргумент 'val'.
|
||||||
|
* Результат помещается в регистр ACC и 40-1 разряды RMR.
|
||||||
|
*/
|
||||||
|
void besm6_multiply (t_value val)
|
||||||
|
{
|
||||||
|
uint8 neg = 0;
|
||||||
|
alureg_t acc, word, a, b;
|
||||||
|
t_uint64 mr, alo, blo, ahi, bhi;
|
||||||
|
|
||||||
|
register t_uint64 l;
|
||||||
|
|
||||||
|
if (! ACC || ! val) {
|
||||||
|
/* multiplication by zero is zero */
|
||||||
|
ACC = 0;
|
||||||
|
RMR &= ~BITS40;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
acc = toalu (ACC);
|
||||||
|
word = toalu (val);
|
||||||
|
|
||||||
|
a = acc;
|
||||||
|
b = word;
|
||||||
|
mr = 0;
|
||||||
|
|
||||||
|
if (is_negative (&a)) {
|
||||||
|
neg = 1;
|
||||||
|
negate (&a);
|
||||||
|
}
|
||||||
|
if (is_negative (&b)) {
|
||||||
|
neg ^= 1;
|
||||||
|
negate (&b);
|
||||||
|
}
|
||||||
|
acc.exponent = a.exponent + b.exponent - 64;
|
||||||
|
|
||||||
|
alo = a.mantissa & BITS(20);
|
||||||
|
ahi = a.mantissa >> 20;
|
||||||
|
|
||||||
|
blo = b.mantissa & BITS(20);
|
||||||
|
bhi = b.mantissa >> 20;
|
||||||
|
|
||||||
|
l = alo * blo + ((alo * bhi + ahi * blo) << 20);
|
||||||
|
|
||||||
|
mr = l & BITS40;
|
||||||
|
l >>= 40;
|
||||||
|
|
||||||
|
acc.mantissa = l + ahi * bhi;
|
||||||
|
|
||||||
|
if (neg) {
|
||||||
|
mr = (~mr & BITS40) + 1;
|
||||||
|
acc.mantissa = ((~acc.mantissa & BITS40) + (mr >> 40))
|
||||||
|
| BIT41 | BIT42;
|
||||||
|
mr &= BITS40;
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_and_round (acc, mr, mr != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Изменение знака числа на сумматоре ACC.
|
||||||
|
* Результат помещается в регистр ACC, RMR гасится.
|
||||||
|
*/
|
||||||
|
void besm6_change_sign (int negate_acc)
|
||||||
|
{
|
||||||
|
alureg_t acc;
|
||||||
|
|
||||||
|
acc = toalu (ACC);
|
||||||
|
if (negate_acc)
|
||||||
|
negate (&acc);
|
||||||
|
RMR = 0;
|
||||||
|
normalize_and_round (acc, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Изменение порядка числа на сумматоре ACC.
|
||||||
|
* Результат помещается в регистр ACC, RMR гасится.
|
||||||
|
*/
|
||||||
|
void besm6_add_exponent (int val)
|
||||||
|
{
|
||||||
|
alureg_t acc;
|
||||||
|
|
||||||
|
acc = toalu (ACC);
|
||||||
|
acc.exponent += val;
|
||||||
|
RMR = 0;
|
||||||
|
normalize_and_round (acc, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Сборка значения по маске.
|
||||||
|
*/
|
||||||
|
t_value besm6_pack (t_value val, t_value mask)
|
||||||
|
{
|
||||||
|
t_value result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (; mask; mask>>=1, val>>=1)
|
||||||
|
if (mask & 1) {
|
||||||
|
result >>= 1;
|
||||||
|
if (val & 1)
|
||||||
|
result |= BIT48;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Разборка значения по маске.
|
||||||
|
*/
|
||||||
|
t_value besm6_unpack (t_value val, t_value mask)
|
||||||
|
{
|
||||||
|
t_value result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (i=0; i<48; ++i) {
|
||||||
|
result <<= 1;
|
||||||
|
if (mask & BIT48) {
|
||||||
|
if (val & BIT48)
|
||||||
|
result |= 1;
|
||||||
|
val <<= 1;
|
||||||
|
}
|
||||||
|
mask <<= 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Подсчёт количества единиц в слове.
|
||||||
|
*/
|
||||||
|
int besm6_count_ones (t_value word)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c=0; word; ++c)
|
||||||
|
word &= word-1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Сдвиг сумматора ACC с выдвижением в регистр младших разрядов RMR.
|
||||||
|
* Величина сдвига находится в диапазоне -64..63.
|
||||||
|
*/
|
||||||
|
void besm6_shift (int i)
|
||||||
|
{
|
||||||
|
RMR = 0;
|
||||||
|
if (i > 0) {
|
||||||
|
/* Сдвиг вправо. */
|
||||||
|
if (i < 48) {
|
||||||
|
RMR = (ACC << (48-i)) & BITS48;
|
||||||
|
ACC >>= i;
|
||||||
|
} else {
|
||||||
|
RMR = ACC >> (i-48);
|
||||||
|
ACC = 0;
|
||||||
|
}
|
||||||
|
} else if (i < 0) {
|
||||||
|
/* Сдвиг влево. */
|
||||||
|
i = -i;
|
||||||
|
if (i < 48) {
|
||||||
|
RMR = ACC >> (48-i);
|
||||||
|
ACC = (ACC << i) & BITS48;
|
||||||
|
} else {
|
||||||
|
RMR = (ACC << (i-48)) & BITS48;
|
||||||
|
ACC = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1764
BESM6/besm6_cpu.c
Normal file
1764
BESM6/besm6_cpu.c
Normal file
File diff suppressed because it is too large
Load diff
426
BESM6/besm6_defs.h
Normal file
426
BESM6/besm6_defs.h
Normal file
|
@ -0,0 +1,426 @@
|
||||||
|
/*
|
||||||
|
* besm6_defs.h: BESM-6 simulator definitions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Serge Vakulenko
|
||||||
|
* Copyright (c) 2009, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#ifndef _BESM6_DEFS_H_
|
||||||
|
#define _BESM6_DEFS_H_ 0
|
||||||
|
|
||||||
|
#include "sim_defs.h" /* simulator defns */
|
||||||
|
#include "scp.h"
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory.
|
||||||
|
*/
|
||||||
|
#define NREGS 30 /* number of registers-modifiers */
|
||||||
|
#define MEMSIZE (512 * 1024) /* memory size, words */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drums and disks.
|
||||||
|
*
|
||||||
|
* One zone contains 1024 words of user memory and 8 system data words.
|
||||||
|
* Every word (t_value) is stored as 8-byte record, low byte first.
|
||||||
|
* System data is stored first, then user data.
|
||||||
|
*/
|
||||||
|
#define ZONE_SIZE (8 + 1024) /* 1kword zone size, words */
|
||||||
|
#define DRUM_SIZE (256 * ZONE_SIZE) /* drum size per controller, words */
|
||||||
|
#define DISK_SIZE (1024 * ZONE_SIZE) /* disk size per unit, words */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simulator stop codes
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
STOP_STOP = 1, /* STOP */
|
||||||
|
STOP_IBKPT, /* SIMH breakpoint */
|
||||||
|
STOP_RWATCH, /* SIMH read watchpoint */
|
||||||
|
STOP_WWATCH, /* SIMH write watchpoint */
|
||||||
|
STOP_RUNOUT, /* run out end of memory limits */
|
||||||
|
STOP_BADCMD, /* invalid instruction */
|
||||||
|
STOP_INSN_CHECK, /* not an instruction */
|
||||||
|
STOP_INSN_PROT, /* fetch from blocked page */
|
||||||
|
STOP_OPERAND_PROT, /* load from blocked page */
|
||||||
|
STOP_RAM_CHECK, /* RAM parity error */
|
||||||
|
STOP_CACHE_CHECK, /* data cache parity error */
|
||||||
|
STOP_OVFL, /* arith. overflow */
|
||||||
|
STOP_DIVZERO, /* division by 0 or denorm */
|
||||||
|
STOP_DOUBLE_INTR, /* double internal interrupt */
|
||||||
|
STOP_DRUMINVDATA, /* reading unformatted drum */
|
||||||
|
STOP_DISKINVDATA, /* reading unformatted disk */
|
||||||
|
STOP_INSN_ADDR_MATCH, /* fetch address matched breakpt reg */
|
||||||
|
STOP_LOAD_ADDR_MATCH, /* load address matched watchpt reg */
|
||||||
|
STOP_STORE_ADDR_MATCH, /* store address matched watchpt reg */
|
||||||
|
STOP_UNIMPLEMENTED, /* unimplemented 033 or 002 insn feature */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Разряды машинного слова, справа налево, начиная с 1.
|
||||||
|
*/
|
||||||
|
#define BBIT(n) (1 << (n-1)) /* один бит, от 1 до 32 */
|
||||||
|
#define BIT40 000010000000000000LL /* 40-й бит - старший разряд мантиссы */
|
||||||
|
#define BIT41 000020000000000000LL /* 41-й бит - знак */
|
||||||
|
#define BIT42 000040000000000000LL /* 42-й бит - дубль-знак в мантиссе */
|
||||||
|
#define BIT48 004000000000000000LL /* 48-й бит - знак порядка */
|
||||||
|
#define BIT49 010000000000000000LL /* бит 49 */
|
||||||
|
#define BITS(n) (~0U >> (32-n)) /* маска битов n..1 */
|
||||||
|
#define BITS40 00017777777777777LL /* биты 41..1 - мантисса */
|
||||||
|
#define BITS41 00037777777777777LL /* биты 41..1 - мантисса и знак */
|
||||||
|
#define BITS42 00077777777777777LL /* биты 42..1 - мантисса и оба знака */
|
||||||
|
#define BITS48 07777777777777777LL /* биты 48..1 */
|
||||||
|
#define BITS48_42 07740000000000000LL /* биты 48..42 - порядок */
|
||||||
|
#define ADDR(x) ((x) & BITS(15)) /* адрес слова */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Работа со сверткой. Значение разрядов свертки слова равно значению
|
||||||
|
* регистров ПКЛ и ПКП при записи слова.
|
||||||
|
* 00 - командная свертка
|
||||||
|
* 01 или 10 - контроль числа
|
||||||
|
* 11 - числовая свертка
|
||||||
|
* В памяти биты свертки имитируют четность полуслов.
|
||||||
|
*/
|
||||||
|
#define CONVOL_INSN 1
|
||||||
|
#define CONVOL_NUMBER 2
|
||||||
|
#define SET_CONVOL(x, c) (((x) & BITS48) | (((c) & 3LL) << 48))
|
||||||
|
#define IS_INSN(x) (((x) >> 48) == CONVOL_INSN)
|
||||||
|
#define IS_NUMBER(x) (((x) >> 48) == CONVOL_INSN || \
|
||||||
|
((x) >> 48) == CONVOL_NUMBER)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Вычисление правдоподобного времени выполнения команды,
|
||||||
|
* зная количество тактов в УУ и среднее в АУ.
|
||||||
|
* Предполагаем, что в 50% случаев происходит совмещение
|
||||||
|
* выполнения, поэтому суммируем большее и половину
|
||||||
|
* от меньшего значения.
|
||||||
|
*/
|
||||||
|
#define MEAN_TIME(x,y) (x>y ? x+y/2 : x/2+y)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Считаем, что моделируеммая машина имеет опорную частоту 10 МГц.
|
||||||
|
*/
|
||||||
|
#define USEC 1 /* одна микросекунда - десять тактов */
|
||||||
|
#define MSEC (1000*USEC) /* одна миллисекунда */
|
||||||
|
#define CLK_TPS 250 /* Fast Clock Ticks Per Second (every 4ms) */
|
||||||
|
#define CLK_DELAY 4000 /* Uncalibrated instructions per clock tick */
|
||||||
|
|
||||||
|
extern UNIT cpu_unit;
|
||||||
|
extern UNIT tty_unit[];
|
||||||
|
extern UNIT clocks[];
|
||||||
|
extern t_value memory [MEMSIZE];
|
||||||
|
extern t_value pult [8];
|
||||||
|
extern uint32 PC, RAU, RUU;
|
||||||
|
extern uint32 M[NREGS];
|
||||||
|
extern t_value BRZ[8], RP[8], GRP, MGRP;
|
||||||
|
extern uint32 PRP, MPRP;
|
||||||
|
extern t_value ACC, RMR;
|
||||||
|
extern uint32 BAZ[8], TABST, RZ;
|
||||||
|
extern uint32 READY; /* read by ext 4031 */
|
||||||
|
extern uint32 READY2; /* read by ext 4102 */
|
||||||
|
extern DEVICE cpu_dev, drum_dev, mmu_dev, disk_dev;
|
||||||
|
extern DEVICE clock_dev;
|
||||||
|
extern DEVICE printer_dev;
|
||||||
|
extern DEVICE tty_dev;
|
||||||
|
extern DEVICE fs_dev;
|
||||||
|
extern jmp_buf cpu_halt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Разряды режима АУ.
|
||||||
|
*/
|
||||||
|
#define RAU_NORM_DISABLE 001 /* блокировка нормализации */
|
||||||
|
#define RAU_ROUND_DISABLE 002 /* блокировка округления */
|
||||||
|
#define RAU_LOG 004 /* признак логической группы */
|
||||||
|
#define RAU_MULT 010 /* признак группы умножения */
|
||||||
|
#define RAU_ADD 020 /* признак группы слодения */
|
||||||
|
#define RAU_OVF_DISABLE 040 /* блокировка переполнения */
|
||||||
|
|
||||||
|
#define RAU_MODE (RAU_LOG | RAU_MULT | RAU_ADD)
|
||||||
|
#define SET_MODE(x,m) (((x) & ~RAU_MODE) | (m))
|
||||||
|
#define SET_LOGICAL(x) (((x) & ~RAU_MODE) | RAU_LOG)
|
||||||
|
#define SET_MULTIPLICATIVE(x) (((x) & ~RAU_MODE) | RAU_MULT)
|
||||||
|
#define SET_ADDITIVE(x) (((x) & ~RAU_MODE) | RAU_ADD)
|
||||||
|
#define IS_LOGICAL(x) (((x) & RAU_MODE) == RAU_LOG)
|
||||||
|
#define IS_MULTIPLICATIVE(x) (((x) & (RAU_ADD | RAU_MULT)) == RAU_MULT)
|
||||||
|
#define IS_ADDITIVE(x) ((x) & RAU_ADD)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Искусственный регистр режимов УУ, в реальной машине отсутствует.
|
||||||
|
*/
|
||||||
|
#define RUU_CONVOL_RIGHT 000001 /* ПКП - признак контроля правой половины */
|
||||||
|
#define RUU_CONVOL_LEFT 000002 /* ПКЛ - признак контроля левой половины */
|
||||||
|
#define RUU_EXTRACODE 000004 /* РежЭ - режим экстракода */
|
||||||
|
#define RUU_INTERRUPT 000010 /* РежПр - режим прерывания */
|
||||||
|
#define RUU_MOD_RK 000020 /* ПрИК - модификация регистром М[16] */
|
||||||
|
#define RUU_AVOST_DISABLE 000040 /* БРО - блокировка режима останова */
|
||||||
|
#define RUU_RIGHT_INSTR 000400 /* ПрК - признак правой команды */
|
||||||
|
|
||||||
|
#define IS_SUPERVISOR(x) ((x) & (RUU_EXTRACODE | RUU_INTERRUPT))
|
||||||
|
#define SET_SUPERVISOR(x,m) (((x) & ~(RUU_EXTRACODE | RUU_INTERRUPT)) | (m))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Специальные регистры.
|
||||||
|
*/
|
||||||
|
#define MOD 020 /* модификатор адреса */
|
||||||
|
#define PSW 021 /* режимы УУ */
|
||||||
|
#define SPSW 027 /* упрятывание режимов УУ */
|
||||||
|
#define ERET 032 /* адрес возврата из экстракода */
|
||||||
|
#define IRET 033 /* адрес возврата из прерывания */
|
||||||
|
#define IBP 034 /* адрес прерывания по выполнению */
|
||||||
|
#define DWP 035 /* адрес прерывания по чтению/записи */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Регистр 021: режимы УУ.
|
||||||
|
* PSW: program status word.
|
||||||
|
*/
|
||||||
|
#define PSW_MMAP_DISABLE 000001 /* БлП - блокировка приписки */
|
||||||
|
#define PSW_PROT_DISABLE 000002 /* БлЗ - блокировка защиты */
|
||||||
|
#define PSW_INTR_HALT 000004 /* ПоП - признак останова при
|
||||||
|
любом внутреннем прерывании */
|
||||||
|
#define PSW_CHECK_HALT 000010 /* ПоК - признак останова при
|
||||||
|
прерывании по контролю */
|
||||||
|
#define PSW_WRITE_WATCH 000020 /* Зп(М29) - признак совпадения адреса
|
||||||
|
операнда прии записи в память
|
||||||
|
с содержанием регистра М29 */
|
||||||
|
#define PSW_INTR_DISABLE 002000 /* БлПр - блокировка внешнего прерывания */
|
||||||
|
#define PSW_AUT_B 004000 /* АвтБ - признак режима Автомат Б */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Регистр 027: сохранённые режимы УУ.
|
||||||
|
* SPSW: saved program status word.
|
||||||
|
*/
|
||||||
|
#define SPSW_MMAP_DISABLE 000001 /* БлП - блокировка приписки */
|
||||||
|
#define SPSW_PROT_DISABLE 000002 /* БлЗ - блокировка защиты */
|
||||||
|
#define SPSW_EXTRACODE 000004 /* РежЭ - режим экстракода */
|
||||||
|
#define SPSW_INTERRUPT 000010 /* РежПр - режим прерывания */
|
||||||
|
#define SPSW_MOD_RK 000020 /* ПрИК(РК) - на регистр РК принята
|
||||||
|
команда, которая должна быть
|
||||||
|
модифицирована регистром М[16] */
|
||||||
|
#define SPSW_MOD_RR 000040 /* ПрИК(РР) - на регистре РР находится
|
||||||
|
команда, выполненная с модификацией */
|
||||||
|
#define SPSW_UNKNOWN 000100 /* НОК? вписано карандашом в 9 томе */
|
||||||
|
#define SPSW_RIGHT_INSTR 000400 /* ПрК - признак правой команды */
|
||||||
|
#define SPSW_NEXT_RK 001000 /* ГД./ДК2 - на регистр РК принята
|
||||||
|
команда, следующая после вызвавшей
|
||||||
|
прерывание */
|
||||||
|
#define SPSW_INTR_DISABLE 002000 /* БлПр - блокировка внешнего прерывания */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Кириллица Unicode.
|
||||||
|
*/
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_A 0x0410
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_BE 0x0411
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_VE 0x0412
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_GHE 0x0413
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_DE 0x0414
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_IE 0x0415
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_ZHE 0x0416
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_ZE 0x0417
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_I 0x0418
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_SHORT_I 0x0419
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_KA 0x041a
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_EL 0x041b
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_EM 0x041c
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_EN 0x041d
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_O 0x041e
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_PE 0x041f
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_ER 0x0420
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_ES 0x0421
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_TE 0x0422
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_U 0x0423
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_EF 0x0424
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_HA 0x0425
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_TSE 0x0426
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_CHE 0x0427
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_SHA 0x0428
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_SHCHA 0x0429
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_HARD_SIGN 0x042a
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_YERU 0x042b
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_SOFT_SIGN 0x042c
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_E 0x042d
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_YU 0x042e
|
||||||
|
#define CYRILLIC_CAPITAL_LETTER_YA 0x042f
|
||||||
|
#define CYRILLIC_SMALL_LETTER_A 0x0430
|
||||||
|
#define CYRILLIC_SMALL_LETTER_BE 0x0431
|
||||||
|
#define CYRILLIC_SMALL_LETTER_VE 0x0432
|
||||||
|
#define CYRILLIC_SMALL_LETTER_GHE 0x0433
|
||||||
|
#define CYRILLIC_SMALL_LETTER_DE 0x0434
|
||||||
|
#define CYRILLIC_SMALL_LETTER_IE 0x0435
|
||||||
|
#define CYRILLIC_SMALL_LETTER_ZHE 0x0436
|
||||||
|
#define CYRILLIC_SMALL_LETTER_ZE 0x0437
|
||||||
|
#define CYRILLIC_SMALL_LETTER_I 0x0438
|
||||||
|
#define CYRILLIC_SMALL_LETTER_SHORT_I 0x0439
|
||||||
|
#define CYRILLIC_SMALL_LETTER_KA 0x043a
|
||||||
|
#define CYRILLIC_SMALL_LETTER_EL 0x043b
|
||||||
|
#define CYRILLIC_SMALL_LETTER_EM 0x043c
|
||||||
|
#define CYRILLIC_SMALL_LETTER_EN 0x043d
|
||||||
|
#define CYRILLIC_SMALL_LETTER_O 0x043e
|
||||||
|
#define CYRILLIC_SMALL_LETTER_PE 0x043f
|
||||||
|
#define CYRILLIC_SMALL_LETTER_ER 0x0440
|
||||||
|
#define CYRILLIC_SMALL_LETTER_ES 0x0441
|
||||||
|
#define CYRILLIC_SMALL_LETTER_TE 0x0442
|
||||||
|
#define CYRILLIC_SMALL_LETTER_U 0x0443
|
||||||
|
#define CYRILLIC_SMALL_LETTER_EF 0x0444
|
||||||
|
#define CYRILLIC_SMALL_LETTER_HA 0x0445
|
||||||
|
#define CYRILLIC_SMALL_LETTER_TSE 0x0446
|
||||||
|
#define CYRILLIC_SMALL_LETTER_CHE 0x0447
|
||||||
|
#define CYRILLIC_SMALL_LETTER_SHA 0x0448
|
||||||
|
#define CYRILLIC_SMALL_LETTER_SHCHA 0x0449
|
||||||
|
#define CYRILLIC_SMALL_LETTER_HARD_SIGN 0x044a
|
||||||
|
#define CYRILLIC_SMALL_LETTER_YERU 0x044b
|
||||||
|
#define CYRILLIC_SMALL_LETTER_SOFT_SIGN 0x044c
|
||||||
|
#define CYRILLIC_SMALL_LETTER_E 0x044d
|
||||||
|
#define CYRILLIC_SMALL_LETTER_YU 0x044e
|
||||||
|
#define CYRILLIC_SMALL_LETTER_YA 0x044f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Процедуры работы с памятью
|
||||||
|
*/
|
||||||
|
extern void mmu_store (int addr, t_value word);
|
||||||
|
extern t_value mmu_load (int addr);
|
||||||
|
extern t_value mmu_fetch (int addr);
|
||||||
|
extern t_value mmu_prefetch (int addr, int actual);
|
||||||
|
extern void mmu_setcache (int idx, t_value word);
|
||||||
|
extern t_value mmu_getcache (int idx);
|
||||||
|
extern void mmu_setrp (int idx, t_value word);
|
||||||
|
extern void mmu_setup (void);
|
||||||
|
extern void mmu_setprotection (int idx, t_value word);
|
||||||
|
extern void mmu_print_brz (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выполнение обращения к барабану.
|
||||||
|
*/
|
||||||
|
void drum (int ctlr, uint32 cmd);
|
||||||
|
int drum_errors (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Обращение к дискам.
|
||||||
|
*/
|
||||||
|
void disk_io (int ctlr, uint32 cmd);
|
||||||
|
void disk_ctl (int ctlr, uint32 cmd);
|
||||||
|
int disk_state (int ctlr);
|
||||||
|
int disk_errors (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Печать на АЦПУ.
|
||||||
|
*/
|
||||||
|
void printer_control (int num, uint32 cmd);
|
||||||
|
void printer_hammer (int num, int pos, uint32 mask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Терминалы (телетайпы, видеотоны, "Консулы").
|
||||||
|
*/
|
||||||
|
void tty_send (uint32 mask);
|
||||||
|
int tty_query (void);
|
||||||
|
void vt_print (void);
|
||||||
|
void tt_print (void);
|
||||||
|
void vt_receive (void);
|
||||||
|
void consul_print (int num, uint32 cmd);
|
||||||
|
uint32 consul_read (int num);
|
||||||
|
int vt_is_idle (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ввод с перфоленты.
|
||||||
|
*/
|
||||||
|
void fs_control (int num, uint32 cmd);
|
||||||
|
int fs_read (int num);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Отладочная выдача.
|
||||||
|
*/
|
||||||
|
void besm6_fprint_cmd (FILE *of, uint32 cmd);
|
||||||
|
void besm6_log (const char *fmt, ...);
|
||||||
|
void besm6_log_cont (const char *fmt, ...);
|
||||||
|
void besm6_debug (const char *fmt, ...);
|
||||||
|
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
void besm6_draw_panel (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Арифметика.
|
||||||
|
*/
|
||||||
|
double besm6_to_ieee (t_value word);
|
||||||
|
void besm6_add (t_value val, int negate_acc, int negate_val);
|
||||||
|
void besm6_divide (t_value val);
|
||||||
|
void besm6_multiply (t_value val);
|
||||||
|
void besm6_change_sign (int sign);
|
||||||
|
void besm6_add_exponent (int val);
|
||||||
|
int besm6_highest_bit (t_value val);
|
||||||
|
void besm6_shift (int toright);
|
||||||
|
int besm6_count_ones (t_value word);
|
||||||
|
t_value besm6_pack (t_value val, t_value mask);
|
||||||
|
t_value besm6_unpack (t_value val, t_value mask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Разряды главного регистра прерываний (ГРП)
|
||||||
|
* Внешние:
|
||||||
|
*/
|
||||||
|
#define GRP_PRN1_SYNC 04000000000000000LL /* 48 */
|
||||||
|
#define GRP_PRN2_SYNC 02000000000000000LL /* 47 */
|
||||||
|
#define GRP_DRUM1_FREE 01000000000000000LL /* 46 */
|
||||||
|
#define GRP_DRUM2_FREE 00400000000000000LL /* 45 */
|
||||||
|
#define GRP_VNIIEM 00300000000000000LL /* 44-43, placeholder */
|
||||||
|
#define GRP_FS1_SYNC 00040000000000000LL /* 42 */
|
||||||
|
#define GRP_FS2_SYNC 00020000000000000LL /* 41 */
|
||||||
|
#define GRP_TIMER 00010000000000000LL /* 40 */
|
||||||
|
#define GRP_PRN1_ZERO 00004000000000000LL /* 39 */
|
||||||
|
#define GRP_PRN2_ZERO 00002000000000000LL /* 38 */
|
||||||
|
#define GRP_SLAVE 00001000000000000LL /* 37 */
|
||||||
|
#define GRP_CHAN3_DONE 00000400000000000LL /* 36 */
|
||||||
|
#define GRP_CHAN4_DONE 00000200000000000LL /* 35 */
|
||||||
|
#define GRP_CHAN5_DONE 00000100000000000LL /* 34 */
|
||||||
|
#define GRP_CHAN6_DONE 00000040000000000LL /* 33 */
|
||||||
|
#define GRP_PANEL_REQ 00000020000000000LL /* 32 */
|
||||||
|
#define GRP_TTY_START 00000010000000000LL /* 31 */
|
||||||
|
#define GRP_IMITATION 00000004000000000LL /* 30 */
|
||||||
|
#define GRP_CHAN3_FREE 00000002000000000LL /* 29 */
|
||||||
|
#define GRP_CHAN4_FREE 00000001000000000LL /* 28 */
|
||||||
|
#define GRP_CHAN5_FREE 00000000400000000LL /* 27 */
|
||||||
|
#define GRP_CHAN6_FREE 00000000200000000LL /* 26 */
|
||||||
|
#define GRP_CHAN7_FREE 00000000100000000LL /* 25 */
|
||||||
|
#define GRP_SERIAL 00000000001000000LL /* 19 */
|
||||||
|
#define GRP_WATCHDOG 00000000000002000LL /* 11 */
|
||||||
|
#define GRP_SLOW_CLK 00000000000001000LL /* 10 */
|
||||||
|
/* Внутренние: */
|
||||||
|
#define GRP_DIVZERO 00000000034000000LL /* 23-21 */
|
||||||
|
#define GRP_OVERFLOW 00000000014000000LL /* 22-21 */
|
||||||
|
#define GRP_CHECK 00000000004000000LL /* 21 */
|
||||||
|
#define GRP_OPRND_PROT 00000000002000000LL /* 20 */
|
||||||
|
#define GRP_WATCHPT_W 00000000000200000LL /* 17 */
|
||||||
|
#define GRP_WATCHPT_R 00000000000100000LL /* 16 */
|
||||||
|
#define GRP_INSN_CHECK 00000000000040000LL /* 15 */
|
||||||
|
#define GRP_INSN_PROT 00000000000020000LL /* 14 */
|
||||||
|
#define GRP_ILL_INSN 00000000000010000LL /* 13 */
|
||||||
|
#define GRP_BREAKPOINT 00000000000004000LL /* 12 */
|
||||||
|
#define GRP_PAGE_MASK 00000000000000760LL /* 9-5 */
|
||||||
|
#define GRP_RAM_CHECK 00000000000000010LL /* 4 */
|
||||||
|
#define GRP_BLOCK_MASK 00000000000000007LL /* 3-1 */
|
||||||
|
|
||||||
|
#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))
|
||||||
|
|
||||||
|
/* Номер блока ОЗУ или номер страницы, вызвавших прерывание */
|
||||||
|
extern uint32 iintr_data;
|
||||||
|
|
||||||
|
#endif
|
703
BESM6/besm6_disk.c
Normal file
703
BESM6/besm6_disk.c
Normal file
|
@ -0,0 +1,703 @@
|
||||||
|
/*
|
||||||
|
* BESM-6 magnetic disk device
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Serge Vakulenko
|
||||||
|
* Copyright (c) 2009, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Управляющее слово обмена с магнитным диском.
|
||||||
|
*/
|
||||||
|
#define DISK_BLOCK 0740000000 /* номер блока памяти - 27-24 рр */
|
||||||
|
#define DISK_READ_SYSDATA 004000000 /* считывание только служебных слов */
|
||||||
|
#define DISK_PAGE_MODE 001000000 /* обмен целой страницей */
|
||||||
|
#define DISK_READ 000400000 /* чтение с диска в память */
|
||||||
|
#define DISK_PAGE 000370000 /* номер страницы памяти */
|
||||||
|
#define DISK_HALFPAGE 000004000 /* выбор половины листа */
|
||||||
|
#define DISK_UNIT 000001600 /* номер устройства */
|
||||||
|
#define DISK_HALFZONE 000000001 /* выбор половины зоны */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "Хороший" статус чтения/записи.
|
||||||
|
* Вычислено по текстам ОС Дубна.
|
||||||
|
* Диспак доволен.
|
||||||
|
*/
|
||||||
|
#define STATUS_GOOD 014000400
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Total size of a disk in blocks, including hidden blocks
|
||||||
|
*/
|
||||||
|
#define DISK_TOTBLK 01767
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Параметры обмена с внешним устройством.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int op; /* Условное слово обмена */
|
||||||
|
int dev; /* Номер устройства, 0..7 */
|
||||||
|
int zone; /* Номер зоны на диске */
|
||||||
|
int track; /* Выбор половины зоны на диске */
|
||||||
|
int memory; /* Начальный адрес памяти */
|
||||||
|
int format; /* Флаг разметки */
|
||||||
|
int status; /* Регистр состояния */
|
||||||
|
t_value mask_grp; /* Маска готовности для ГРП */
|
||||||
|
int mask_fail; /* Маска ошибки обмена */
|
||||||
|
t_value *sysdata; /* Буфер системных данных */
|
||||||
|
} KMD;
|
||||||
|
|
||||||
|
static KMD controller [2]; /* Две стойки КМД */
|
||||||
|
int disk_fail; /* Маска ошибок по направлениям */
|
||||||
|
|
||||||
|
t_stat disk_event (UNIT *u);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DISK data structures
|
||||||
|
*
|
||||||
|
* disk_dev DISK device descriptor
|
||||||
|
* disk_unit DISK unit descriptor
|
||||||
|
* disk_reg DISK register list
|
||||||
|
*/
|
||||||
|
UNIT disk_unit [16] = {
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
{ UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DISK_SIZE) },
|
||||||
|
};
|
||||||
|
|
||||||
|
REG disk_reg[] = {
|
||||||
|
{ "КУС_0", &controller[0].op, 8, 24, 0, 1 },
|
||||||
|
{ "УСТР_0", &controller[0].dev, 8, 3, 0, 1 },
|
||||||
|
{ "ЗОНА_0", &controller[0].zone, 8, 10, 0, 1 },
|
||||||
|
{ "ДОРОЖКА_0", &controller[0].track, 8, 2, 0, 1 },
|
||||||
|
{ "МОЗУ_0", &controller[0].memory, 8, 20, 0, 1 },
|
||||||
|
{ "РС_0", &controller[0].status, 8, 24, 0, 1 },
|
||||||
|
{ "КУС_1", &controller[1].op, 8, 24, 0, 1 },
|
||||||
|
{ "УСТР_1", &controller[1].dev, 8, 3, 0, 1 },
|
||||||
|
{ "ЗОНА_1", &controller[1].zone, 8, 10, 0, 1 },
|
||||||
|
{ "ДОРОЖКА_1", &controller[1].track, 8, 2, 0, 1 },
|
||||||
|
{ "МОЗУ_1", &controller[1].memory, 8, 20, 0, 1 },
|
||||||
|
{ "РС_1", &controller[1].status, 8, 24, 0, 1 },
|
||||||
|
{ "ОШ", &disk_fail, 8, 6, 0, 1 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
MTAB disk_mod[] = {
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
t_stat disk_reset (DEVICE *dptr);
|
||||||
|
t_stat disk_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat disk_detach (UNIT *uptr);
|
||||||
|
|
||||||
|
DEVICE disk_dev = {
|
||||||
|
"DISK", disk_unit, disk_reg, disk_mod,
|
||||||
|
16, 8, 21, 1, 8, 50,
|
||||||
|
NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach,
|
||||||
|
NULL, DEV_DISABLE | DEV_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Определение контроллера по устройству.
|
||||||
|
*/
|
||||||
|
static KMD *unit_to_ctlr (UNIT *u)
|
||||||
|
{
|
||||||
|
if (u < &disk_unit[8])
|
||||||
|
return &controller[0];
|
||||||
|
else
|
||||||
|
return &controller[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset routine
|
||||||
|
*/
|
||||||
|
t_stat disk_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset (&controller, 0, sizeof (controller));
|
||||||
|
controller[0].sysdata = &memory [030];
|
||||||
|
controller[1].sysdata = &memory [040];
|
||||||
|
controller[0].mask_grp = GRP_CHAN3_FREE;
|
||||||
|
controller[1].mask_grp = GRP_CHAN4_FREE;
|
||||||
|
controller[0].mask_fail = 020;
|
||||||
|
controller[1].mask_fail = 010;
|
||||||
|
for (i=0; i<16; ++i)
|
||||||
|
sim_cancel (&disk_unit[i]);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat disk_attach (UNIT *u, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat s;
|
||||||
|
int32 saved_switches = sim_switches;
|
||||||
|
sim_switches |= SWMASK ('E');
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
s = attach_unit (u, cptr);
|
||||||
|
if ((s == SCPE_OK) && (sim_switches & SWMASK ('N'))) {
|
||||||
|
t_value control[4]; /* block (zone) number, key, userid, checksum */
|
||||||
|
int diskno, blkno, word;
|
||||||
|
char *pos;
|
||||||
|
/* Using the rightmost sequence of digits within the filename
|
||||||
|
* as a volume number, e.g. "/var/tmp/besm6/2052.bin" -> 2052
|
||||||
|
*/
|
||||||
|
pos = cptr + strlen(cptr);
|
||||||
|
while (pos > cptr && !isdigit(*--pos));
|
||||||
|
while (pos > cptr && isdigit(*pos)) --pos;
|
||||||
|
if (!isdigit(*pos)) ++pos;
|
||||||
|
diskno = atoi(pos);
|
||||||
|
if (diskno < 2048 || diskno > 4095) {
|
||||||
|
if (diskno == 0)
|
||||||
|
sim_printf ("%s: filename must contain volume number 2048..4095\n", sim_uname(u));
|
||||||
|
else
|
||||||
|
sim_printf ("%s: disk volume %d from filename %s invalid (must be 2048..4095)\n",
|
||||||
|
sim_uname (u), diskno, cptr);
|
||||||
|
/* unlink (cptr); ??? */
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
if (!sim_quiet && !(sim_switches & SWMASK ('Q')))
|
||||||
|
sim_printf ("%s: formatting disk volume %d\n", sim_uname (u), diskno);
|
||||||
|
|
||||||
|
control[1] = SET_CONVOL(0, CONVOL_NUMBER);
|
||||||
|
control[2] = SET_CONVOL(0, CONVOL_NUMBER);
|
||||||
|
control[3] = SET_CONVOL(0, CONVOL_NUMBER);
|
||||||
|
|
||||||
|
control[1] |= 01370707LL << 24; /* Magic mark */
|
||||||
|
control[1] |= diskno << 12;
|
||||||
|
|
||||||
|
for (blkno = 0; blkno < DISK_TOTBLK; ++blkno) {
|
||||||
|
control[0] = SET_CONVOL((t_value)(2*blkno) << 36, CONVOL_NUMBER);
|
||||||
|
sim_fwrite(control, sizeof(t_value), 4, u->fileref);
|
||||||
|
control[0] = SET_CONVOL((t_value)(2*blkno+1) << 36, CONVOL_NUMBER);
|
||||||
|
sim_fwrite(control, sizeof(t_value), 4, u->fileref);
|
||||||
|
for (word = 0; word < 02000; ++word) {
|
||||||
|
sim_fwrite(control+2, sizeof(t_value), 1, u->fileref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (s == SCPE_OK ||
|
||||||
|
(saved_switches & SWMASK ('E')) ||
|
||||||
|
(sim_switches & SWMASK('N')))
|
||||||
|
return s;
|
||||||
|
sim_switches |= SWMASK ('N');
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat disk_detach (UNIT *u)
|
||||||
|
{
|
||||||
|
/* TODO: сброс бита ГРП готовности направления при отключении последнего диска. */
|
||||||
|
return detach_unit (u);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_value spread (t_value val)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
t_value res = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) for (j = 0; j < 9; j++)
|
||||||
|
if (val & (1LL<<(i+j*5)))
|
||||||
|
res |= 1LL << (i*9+j);
|
||||||
|
return res & BITS48;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Отладочная печать массива данных обмена.
|
||||||
|
*/
|
||||||
|
static void log_data (t_value *data, int nwords)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
t_value val;
|
||||||
|
|
||||||
|
for (i=0; i<nwords; ++i) {
|
||||||
|
val = data[i];
|
||||||
|
fprintf (sim_log, " %04o-%04o-%04o-%04o",
|
||||||
|
(int) (val >> 36) & 07777,
|
||||||
|
(int) (val >> 24) & 07777,
|
||||||
|
(int) (val >> 12) & 07777,
|
||||||
|
(int) val & 07777);
|
||||||
|
if ((i & 3) == 3)
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
}
|
||||||
|
if ((i & 3) != 0)
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Сложение с переносом вправо.
|
||||||
|
*/
|
||||||
|
static unsigned sum_with_right_carry (unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned c;
|
||||||
|
|
||||||
|
while (b) {
|
||||||
|
c = a & b;
|
||||||
|
a ^= b;
|
||||||
|
b = c >> 1;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Запись на диск.
|
||||||
|
*/
|
||||||
|
void disk_write (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: запись МД %o зона %04o память %05o-%05o",
|
||||||
|
c->dev, c->zone, c->memory, c->memory + 1023);
|
||||||
|
fseek (u->fileref, ZONE_SIZE * c->zone * 8, SEEK_SET);
|
||||||
|
sim_fwrite (c->sysdata, 8, 8, u->fileref);
|
||||||
|
sim_fwrite (&memory [c->memory], 8, 1024, u->fileref);
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disk_write_track (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: запись МД %o полузона %04o.%d память %05o-%05o",
|
||||||
|
c->dev, c->zone, c->track, c->memory, c->memory + 511);
|
||||||
|
fseek (u->fileref, (ZONE_SIZE*c->zone + 4*c->track) * 8, SEEK_SET);
|
||||||
|
sim_fwrite (c->sysdata + 4*c->track, 8, 4, u->fileref);
|
||||||
|
fseek (u->fileref, (8 + ZONE_SIZE*c->zone + 512*c->track) * 8,
|
||||||
|
SEEK_SET);
|
||||||
|
sim_fwrite (&memory [c->memory], 8, 512, u->fileref);
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Форматирование дорожки.
|
||||||
|
*/
|
||||||
|
void disk_format (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
t_value fmtbuf[5], *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* По сути, эмулятору ничего делать не надо. */
|
||||||
|
if (! disk_dev.dctrl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Находим начало записываемого заголовка. */
|
||||||
|
ptr = &memory [c->memory];
|
||||||
|
while ((*ptr & BITS48) == 0)
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
/* Декодируем из гребенки в нормальный вид. */
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
fmtbuf[i] = spread (ptr[i]);
|
||||||
|
|
||||||
|
/* При первой попытке разметки адресный маркер начинается в старшем 5-разрядном слоге,
|
||||||
|
* пропускаем первый слог. */
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
fmtbuf[i] = ((fmtbuf[i] & BITS48) << 5) |
|
||||||
|
((fmtbuf[i+1] >> 40) & BITS(5));
|
||||||
|
|
||||||
|
/* Печатаем идентификатор, адрес и контрольную сумму адреса. */
|
||||||
|
besm6_debug ("::: формат МД %o полузона %04o.%d память %05o и-а-кса %010o %010o",
|
||||||
|
c->dev, c->zone, c->track, c->memory,
|
||||||
|
(int) (fmtbuf[0] >> 8 & BITS(30)),
|
||||||
|
(int) (fmtbuf[2] >> 14 & BITS(30)));
|
||||||
|
/* log_data (fmtbuf, 4); */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Чтение с диска.
|
||||||
|
*/
|
||||||
|
void disk_read (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ((c->op & DISK_READ_SYSDATA) ?
|
||||||
|
"::: чтение МД %o зона %04o служебные слова" :
|
||||||
|
"::: чтение МД %o зона %04o память %05o-%05o",
|
||||||
|
c->dev, c->zone, c->memory, c->memory + 1023);
|
||||||
|
fseek (u->fileref, ZONE_SIZE * c->zone * 8, SEEK_SET);
|
||||||
|
if (sim_fread (c->sysdata, 8, 8, u->fileref) != 8) {
|
||||||
|
/* Чтение неинициализированного диска */
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! (c->op & DISK_READ_SYSDATA) &&
|
||||||
|
sim_fread (&memory [c->memory], 8, 1024, u->fileref) != 1024) {
|
||||||
|
/* Чтение неинициализированного диска */
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_value collect (t_value val)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
t_value res = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) for (j = 0; j < 9; j++)
|
||||||
|
if (val & (1LL<<(i*9+j)))
|
||||||
|
res |= 1LL << (i+j*5);
|
||||||
|
return res & BITS48;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disk_read_track (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ((c->op & DISK_READ_SYSDATA) ?
|
||||||
|
"::: чтение МД %o полузона %04o.%d служебные слова" :
|
||||||
|
"::: чтение МД %o полузона %04o.%d память %05o-%05o",
|
||||||
|
c->dev, c->zone, c->track, c->memory, c->memory + 511);
|
||||||
|
fseek (u->fileref, (ZONE_SIZE*c->zone + 4*c->track) * 8, SEEK_SET);
|
||||||
|
if (sim_fread (c->sysdata + 4*c->track, 8, 4, u->fileref) != 4) {
|
||||||
|
/* Чтение неинициализированного диска */
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! (c->op & DISK_READ_SYSDATA)) {
|
||||||
|
fseek (u->fileref, (8 + ZONE_SIZE*c->zone + 512*c->track) * 8,
|
||||||
|
SEEK_SET);
|
||||||
|
if (sim_fread (&memory [c->memory], 8, 512, u->fileref) != 512) {
|
||||||
|
/* Чтение неинициализированного диска */
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Чтение заголовка дорожки.
|
||||||
|
*/
|
||||||
|
void disk_read_header (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
t_value *sysdata = c->sysdata + 4*c->track;
|
||||||
|
int iaksa, i, cyl, head;
|
||||||
|
|
||||||
|
/* Адрес: номер цилиндра и головки. */
|
||||||
|
head = (c->zone << 1) + c->track;
|
||||||
|
cyl = head / 10;
|
||||||
|
head %= 10;
|
||||||
|
iaksa = (cyl << 20) | (head << 16);
|
||||||
|
|
||||||
|
/* Идентификатор дорожки замены. */
|
||||||
|
if (c->zone >= 01750)
|
||||||
|
iaksa |= BBIT(30);
|
||||||
|
|
||||||
|
/* Контрольная сумма адреса с переносом вправо. */
|
||||||
|
iaksa |= BITS(12) & ~sum_with_right_carry (iaksa >> 12, iaksa >> 24);
|
||||||
|
|
||||||
|
/* Амиакса, 42 нуля, амиакса, много единиц. */
|
||||||
|
sysdata[0] = 07404000000000000LL | (t_value) iaksa << 8;
|
||||||
|
sysdata[1] = 03740LL;
|
||||||
|
sysdata[2] = 00400000000037777LL | (t_value) iaksa << 14;
|
||||||
|
sysdata[3] = BITS48;
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
log_data (sysdata, 4);
|
||||||
|
|
||||||
|
/* Кодируем гребенку. */
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
sysdata[i] = SET_CONVOL (collect (sysdata[i]), CONVOL_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Задание адреса памяти и длины массива для последующего обращения к диску.
|
||||||
|
* Номера дисковода и дорожки будут выданы позже, командой 033 0023(0024).
|
||||||
|
*/
|
||||||
|
void disk_io (int ctlr, uint32 cmd)
|
||||||
|
{
|
||||||
|
KMD *c = &controller [ctlr];
|
||||||
|
|
||||||
|
c->op = cmd;
|
||||||
|
c->format = 0;
|
||||||
|
if (c->op & DISK_PAGE_MODE) {
|
||||||
|
/* Обмен страницей */
|
||||||
|
c->memory = (cmd & DISK_PAGE) >> 2 | (cmd & DISK_BLOCK) >> 8;
|
||||||
|
} else {
|
||||||
|
/* Обмен половиной страницы (дорожкой) */
|
||||||
|
c->memory = (cmd & (DISK_PAGE | DISK_HALFPAGE)) >> 2 | (cmd & DISK_BLOCK) >> 8;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: задание на %s %08o", ctlr + '3',
|
||||||
|
(c->op & DISK_READ) ? "чтение" : "запись", cmd);
|
||||||
|
#endif
|
||||||
|
disk_fail &= ~c->mask_fail;
|
||||||
|
|
||||||
|
/* Гасим главный регистр прерываний. */
|
||||||
|
GRP &= ~c->mask_grp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Управление диском: команда 00 033 0023(0024).
|
||||||
|
*/
|
||||||
|
void disk_ctl (int ctlr, uint32 cmd)
|
||||||
|
{
|
||||||
|
KMD *c = &controller [ctlr];
|
||||||
|
UNIT *u = &disk_unit [c->dev];
|
||||||
|
|
||||||
|
if (cmd & BBIT(12)) {
|
||||||
|
/* Выдача в КМД адреса дорожки.
|
||||||
|
* Здесь же выполняем обмен с диском.
|
||||||
|
* Номер дисковода к этому моменту уже известен. */
|
||||||
|
if ((disk_dev.flags & DEV_DIS) || ! (u->flags & UNIT_ATT)) {
|
||||||
|
/* Device not attached. */
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->zone = (cmd >> 1) & BITS(10);
|
||||||
|
c->track = cmd & 1;
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: выдача адреса дорожки %04o.%d",
|
||||||
|
ctlr + '3', c->zone, c->track);
|
||||||
|
#endif
|
||||||
|
disk_fail &= ~c->mask_fail;
|
||||||
|
if (c->op & DISK_READ) {
|
||||||
|
if (c->op & DISK_PAGE_MODE)
|
||||||
|
disk_read (u);
|
||||||
|
else
|
||||||
|
disk_read_track (u);
|
||||||
|
} else {
|
||||||
|
if (u->flags & UNIT_RO) {
|
||||||
|
/* Read only. */
|
||||||
|
/*longjmp (cpu_halt, SCPE_RO);*/
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c->format)
|
||||||
|
disk_format (u);
|
||||||
|
else if (c->op & DISK_PAGE_MODE)
|
||||||
|
disk_write (u);
|
||||||
|
else
|
||||||
|
disk_write_track (u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ждём события от устройства. */
|
||||||
|
sim_activate (u, 20*USEC); /* Ускорим для отладки. */
|
||||||
|
|
||||||
|
} else if (cmd & BBIT(11)) {
|
||||||
|
/* Выбора номера устройства и занесение в регистр маски КМД.
|
||||||
|
* Бит 8 - устройство 0, бит 7 - устройство 1, ... бит 1 - устройство 7.
|
||||||
|
* Также установлен бит 9 - что он означает? */
|
||||||
|
if (cmd & BBIT(8)) c->dev = 7;
|
||||||
|
else if (cmd & BBIT(7)) c->dev = 6;
|
||||||
|
else if (cmd & BBIT(6)) c->dev = 5;
|
||||||
|
else if (cmd & BBIT(5)) c->dev = 4;
|
||||||
|
else if (cmd & BBIT(4)) c->dev = 3;
|
||||||
|
else if (cmd & BBIT(3)) c->dev = 2;
|
||||||
|
else if (cmd & BBIT(2)) c->dev = 1;
|
||||||
|
else if (cmd & BBIT(1)) c->dev = 0;
|
||||||
|
else {
|
||||||
|
/* Неверная маска выбора устройства. */
|
||||||
|
c->dev = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->dev += ctlr << 3;
|
||||||
|
u = &disk_unit[c->dev];
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: выбор устройства %d",
|
||||||
|
ctlr + '3', c->dev);
|
||||||
|
#endif
|
||||||
|
if ((disk_dev.flags & DEV_DIS) || ! (u->flags & UNIT_ATT)) {
|
||||||
|
/* Device not attached. */
|
||||||
|
disk_fail |= c->mask_fail;
|
||||||
|
GRP &= ~c->mask_grp;
|
||||||
|
}
|
||||||
|
GRP |= c->mask_grp;
|
||||||
|
|
||||||
|
} else if (cmd & BBIT(9)) {
|
||||||
|
/* Проверка прерывания от КМД? */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: проверка готовности",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
GRP |= c->mask_grp;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Команда, выдаваемая в КМД. */
|
||||||
|
switch (cmd & 077) {
|
||||||
|
case 000: /* диспак выдаёт эту команду один раз в начале загрузки */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: недокументированная команда 00",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 001: /* сброс на 0 цилиндр */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: сброс на 0 цилиндр",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 002: /* подвод */
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: подвод", ctlr + '3');
|
||||||
|
break;
|
||||||
|
case 003: /* чтение (НСМД-МОЗУ) */
|
||||||
|
case 043: /* резервной дорожки */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: чтение", ctlr + '3');
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 004: /* запись (МОЗУ-НСМД) */
|
||||||
|
case 044: /* резервной дорожки */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: запись", ctlr + '3');
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 005: /* разметка */
|
||||||
|
c->format = 1;
|
||||||
|
break;
|
||||||
|
case 006: /* сравнение кодов (МОЗУ-НСМД) */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: сравнение кодов", ctlr + '3');
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 007: /* чтение заголовка */
|
||||||
|
case 047: /* резервной дорожки */
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: чтение %s заголовка", ctlr + '3',
|
||||||
|
cmd & 040 ? "резервного" : "");
|
||||||
|
disk_fail &= ~c->mask_fail;
|
||||||
|
disk_read_header (u);
|
||||||
|
|
||||||
|
/* Ждём события от устройства. */
|
||||||
|
sim_activate (u, 20*USEC); /* Ускорим для отладки. */
|
||||||
|
break;
|
||||||
|
case 010: /* гашение PC */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: гашение регистра состояния",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
c->status = 0;
|
||||||
|
break;
|
||||||
|
case 011: /* опрос 1÷12 разрядов PC */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: опрос младших разрядов состояния",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
if (disk_unit[c->dev].flags & UNIT_ATT)
|
||||||
|
c->status = STATUS_GOOD & BITS(12);
|
||||||
|
else
|
||||||
|
c->status = 0;
|
||||||
|
break;
|
||||||
|
case 031: /* опрос 13÷24 разрядов РС */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: опрос старших разрядов состояния",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
if (disk_unit[c->dev].flags & UNIT_ATT)
|
||||||
|
c->status = (STATUS_GOOD >> 12) & BITS(12);
|
||||||
|
else
|
||||||
|
c->status = 0;
|
||||||
|
break;
|
||||||
|
case 050: /* освобождение НМД */
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: освобождение накопителя",
|
||||||
|
ctlr + '3');
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
besm6_debug ("::: КМД %c: неизвестная команда %02o",
|
||||||
|
ctlr + '3', cmd & 077);
|
||||||
|
GRP |= c->mask_grp; /* чтобы не зависало */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Запрос состояния контроллера.
|
||||||
|
*/
|
||||||
|
int disk_state (int ctlr)
|
||||||
|
{
|
||||||
|
KMD *c = &controller [ctlr];
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД %c: опрос состояния = %04o",
|
||||||
|
ctlr + '3', c->status);
|
||||||
|
#endif
|
||||||
|
return c->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Событие: закончен обмен с МД.
|
||||||
|
* Устанавливаем флаг прерывания.
|
||||||
|
*/
|
||||||
|
t_stat disk_event (UNIT *u)
|
||||||
|
{
|
||||||
|
KMD *c = unit_to_ctlr (u);
|
||||||
|
|
||||||
|
GRP |= c->mask_grp;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Опрос ошибок обмена командой 033 4035.
|
||||||
|
*/
|
||||||
|
int disk_errors ()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (disk_dev.dctrl)
|
||||||
|
besm6_debug ("::: КМД: опрос шкалы ошибок = %04o", disk_fail);
|
||||||
|
#endif
|
||||||
|
return disk_fail;
|
||||||
|
}
|
372
BESM6/besm6_drum.c
Normal file
372
BESM6/besm6_drum.c
Normal file
|
@ -0,0 +1,372 @@
|
||||||
|
/*
|
||||||
|
* besm6_drum.c: BESM-6 magnetic drum device
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Serge Vakulenko
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Управляющее слово обмена с магнитным барабаном.
|
||||||
|
*/
|
||||||
|
#define DRUM_READ_OVERLAY 020000000 /* считывание с наложением */
|
||||||
|
#define DRUM_PARITY_FLAG 010000000 /* блокировка считывания слов с неверной
|
||||||
|
* чётностью или запись с неверной чётностью */
|
||||||
|
#define DRUM_READ_SYSDATA 004000000 /* считывание только служебных слов */
|
||||||
|
#define DRUM_PAGE_MODE 001000000 /* обмен целой страницей */
|
||||||
|
#define DRUM_READ 000400000 /* чтение с барабана в память */
|
||||||
|
#define DRUM_PAGE 000370000 /* номер страницы памяти */
|
||||||
|
#define DRUM_BLOCK 0740000000 /* номер блока памяти - 27-24 рр */
|
||||||
|
#define DRUM_PARAGRAF 000006000 /* номер абзаца */
|
||||||
|
#define DRUM_UNIT 000001600 /* номер барабана */
|
||||||
|
#define DRUM_CYLINDER 000000174 /* номер тракта на барабане */
|
||||||
|
#define DRUM_SECTOR 000000003 /* номер сектора */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Параметры обмена с внешним устройством.
|
||||||
|
*/
|
||||||
|
int drum_op; /* Условное слово обмена */
|
||||||
|
int drum_zone; /* Номер зоны на барабане */
|
||||||
|
int drum_sector; /* Начальный номер сектора на барабане */
|
||||||
|
int drum_memory; /* Начальный адрес памяти */
|
||||||
|
int drum_nwords; /* Количество слов обмена */
|
||||||
|
int drum_fail; /* Маска ошибок по направлениям */
|
||||||
|
|
||||||
|
t_stat drum_event (UNIT *u);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DRUM data structures
|
||||||
|
*
|
||||||
|
* drum_dev DRUM device descriptor
|
||||||
|
* drum_unit DRUM unit descriptor
|
||||||
|
* drum_reg DRUM register list
|
||||||
|
*/
|
||||||
|
UNIT drum_unit [] = {
|
||||||
|
{ UDATA (drum_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DRUM_SIZE) },
|
||||||
|
{ UDATA (drum_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, DRUM_SIZE) },
|
||||||
|
};
|
||||||
|
|
||||||
|
REG drum_reg[] = {
|
||||||
|
{ "УС", &drum_op, 8, 24, 0, 1 },
|
||||||
|
{ "ЗОНА", &drum_zone, 8, 10, 0, 1 },
|
||||||
|
{ "СЕКТОР", &drum_sector, 8, 2, 0, 1 },
|
||||||
|
{ "МОЗУ", &drum_memory, 8, 15, 0, 1 },
|
||||||
|
{ "СЧСЛОВ", &drum_nwords, 8, 11, 0, 1 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
MTAB drum_mod[] = {
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
t_stat drum_reset (DEVICE *dptr);
|
||||||
|
t_stat drum_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat drum_detach (UNIT *uptr);
|
||||||
|
|
||||||
|
DEVICE drum_dev = {
|
||||||
|
"DRUM", drum_unit, drum_reg, drum_mod,
|
||||||
|
2, 8, 19, 1, 8, 50,
|
||||||
|
NULL, NULL, &drum_reset, NULL, &drum_attach, &drum_detach,
|
||||||
|
NULL, DEV_DISABLE | DEV_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset routine
|
||||||
|
*/
|
||||||
|
t_stat drum_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
drum_op = 0;
|
||||||
|
drum_zone = 0;
|
||||||
|
drum_sector = 0;
|
||||||
|
drum_memory = 0;
|
||||||
|
drum_nwords = 0;
|
||||||
|
sim_cancel (&drum_unit[0]);
|
||||||
|
sim_cancel (&drum_unit[1]);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat drum_attach (UNIT *u, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat s;
|
||||||
|
|
||||||
|
s = attach_unit (u, cptr);
|
||||||
|
if (s != SCPE_OK)
|
||||||
|
return s;
|
||||||
|
if (u == &drum_unit[0])
|
||||||
|
GRP |= GRP_DRUM1_FREE;
|
||||||
|
else
|
||||||
|
GRP |= GRP_DRUM2_FREE;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat drum_detach (UNIT *u)
|
||||||
|
{
|
||||||
|
if (u == &drum_unit[0])
|
||||||
|
GRP &= ~GRP_DRUM1_FREE;
|
||||||
|
else
|
||||||
|
GRP &= ~GRP_DRUM2_FREE;
|
||||||
|
return detach_unit (u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Отладочная печать массива данных обмена.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
static void log_io (UNIT *u)
|
||||||
|
{
|
||||||
|
t_value *data, *sysdata;
|
||||||
|
int i;
|
||||||
|
void print_word (t_value val) {
|
||||||
|
fprintf (sim_log, " %o-%04o-%04o-%04o-%04o",
|
||||||
|
(int) (val >> 48) & 07,
|
||||||
|
(int) (val >> 36) & 07777,
|
||||||
|
(int) (val >> 24) & 07777,
|
||||||
|
(int) (val >> 12) & 07777, (int) val & 07777);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = &memory [drum_memory];
|
||||||
|
sysdata = (u == &drum_unit[0]) ? &memory [010] : &memory [020];
|
||||||
|
if (drum_nwords == 1024) {
|
||||||
|
fprintf (sim_log, "=== зона МБ %d.%03o:",
|
||||||
|
(u == &drum_unit[0]) ? 1 : 2, drum_zone);
|
||||||
|
for (i=0; i<8; ++i)
|
||||||
|
print_word (sysdata[i]);
|
||||||
|
} else {
|
||||||
|
sysdata += drum_sector*2;
|
||||||
|
fprintf (sim_log, "=== сектор МБ %d.%03o.%o:",
|
||||||
|
(u == &drum_unit[0]) ? 1 : 2,
|
||||||
|
drum_zone, drum_sector);
|
||||||
|
for (i=0; i<2; ++i)
|
||||||
|
print_word (sysdata[i]);
|
||||||
|
}
|
||||||
|
if (! (drum_op & DRUM_READ_SYSDATA)) {
|
||||||
|
fprintf (sim_log, "\n\t\t ");
|
||||||
|
for (i=0; i<drum_nwords; ++i)
|
||||||
|
print_word (data[i]);
|
||||||
|
}
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Запись на барабан.
|
||||||
|
*/
|
||||||
|
void drum_write (UNIT *u)
|
||||||
|
{
|
||||||
|
int ctlr;
|
||||||
|
t_value *sysdata;
|
||||||
|
|
||||||
|
ctlr = (u == &drum_unit[1]);
|
||||||
|
sysdata = ctlr ? &memory [020] : &memory [010];
|
||||||
|
fseek (u->fileref, ZONE_SIZE * drum_zone * 8, SEEK_SET);
|
||||||
|
sim_fwrite (sysdata, 8, 8, u->fileref);
|
||||||
|
sim_fwrite (&memory [drum_memory], 8, 1024, u->fileref);
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drum_write_sector (UNIT *u)
|
||||||
|
{
|
||||||
|
int ctlr;
|
||||||
|
t_value *sysdata;
|
||||||
|
|
||||||
|
ctlr = (u == &drum_unit[1]);
|
||||||
|
sysdata = ctlr ? &memory [020] : &memory [010];
|
||||||
|
fseek (u->fileref, (ZONE_SIZE*drum_zone + drum_sector*2) * 8,
|
||||||
|
SEEK_SET);
|
||||||
|
sim_fwrite (&sysdata [drum_sector*2], 8, 2, u->fileref);
|
||||||
|
fseek (u->fileref, (ZONE_SIZE*drum_zone + 8 + drum_sector*256) * 8,
|
||||||
|
SEEK_SET);
|
||||||
|
sim_fwrite (&memory [drum_memory], 8, 256, u->fileref);
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Чтение с барабана.
|
||||||
|
*/
|
||||||
|
void drum_read (UNIT *u)
|
||||||
|
{
|
||||||
|
int ctlr;
|
||||||
|
t_value *sysdata;
|
||||||
|
|
||||||
|
ctlr = (u == &drum_unit[1]);
|
||||||
|
sysdata = ctlr ? &memory [020] : &memory [010];
|
||||||
|
fseek (u->fileref, ZONE_SIZE * drum_zone * 8, SEEK_SET);
|
||||||
|
if (sim_fread (sysdata, 8, 8, u->fileref) != 8) {
|
||||||
|
/* Чтение неинициализированного барабана */
|
||||||
|
drum_fail |= 0100 >> ctlr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! (drum_op & DRUM_READ_SYSDATA) &&
|
||||||
|
sim_fread (&memory[drum_memory], 8, 1024, u->fileref) != 1024) {
|
||||||
|
/* Чтение неинициализированного барабана */
|
||||||
|
drum_fail |= 0100 >> ctlr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drum_read_sector (UNIT *u)
|
||||||
|
{
|
||||||
|
int ctlr;
|
||||||
|
t_value *sysdata;
|
||||||
|
|
||||||
|
ctlr = (u == &drum_unit[1]);
|
||||||
|
sysdata = ctlr ? &memory [020] : &memory [010];
|
||||||
|
fseek (u->fileref, (ZONE_SIZE*drum_zone + drum_sector*2) * 8, SEEK_SET);
|
||||||
|
if (sim_fread (&sysdata [drum_sector*2], 8, 2, u->fileref) != 2) {
|
||||||
|
/* Чтение неинициализированного барабана */
|
||||||
|
drum_fail |= 0100 >> ctlr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! (drum_op & DRUM_READ_SYSDATA)) {
|
||||||
|
fseek (u->fileref, (ZONE_SIZE*drum_zone + 8 + drum_sector*256) * 8,
|
||||||
|
SEEK_SET);
|
||||||
|
if (sim_fread (&memory[drum_memory], 8, 256, u->fileref) != 256) {
|
||||||
|
/* Чтение неинициализированного барабана */
|
||||||
|
drum_fail |= 0100 >> ctlr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ferror (u->fileref))
|
||||||
|
longjmp (cpu_halt, SCPE_IOERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_memory (t_value *p, int nwords)
|
||||||
|
{
|
||||||
|
while (nwords-- > 0)
|
||||||
|
*p++ = SET_CONVOL (0, CONVOL_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выполнение обращения к барабану.
|
||||||
|
*/
|
||||||
|
void drum (int ctlr, uint32 cmd)
|
||||||
|
{
|
||||||
|
UNIT *u = &drum_unit[ctlr];
|
||||||
|
|
||||||
|
drum_op = cmd;
|
||||||
|
if (drum_op & DRUM_PAGE_MODE) {
|
||||||
|
/* Обмен страницей */
|
||||||
|
drum_nwords = 1024;
|
||||||
|
drum_zone = (cmd & (DRUM_UNIT | DRUM_CYLINDER)) >> 2;
|
||||||
|
drum_sector = 0;
|
||||||
|
drum_memory = (cmd & DRUM_PAGE) >> 2 | (cmd & DRUM_BLOCK) >> 8;
|
||||||
|
if (drum_dev.dctrl)
|
||||||
|
besm6_debug ("### %s МБ %c%d зона %02o память %05o-%05o",
|
||||||
|
(drum_op & DRUM_READ) ? "чтение" : "запись",
|
||||||
|
ctlr + '1', (drum_zone >> 5 & 7), drum_zone & 037,
|
||||||
|
drum_memory, drum_memory + drum_nwords - 1);
|
||||||
|
if (drum_op & DRUM_READ) {
|
||||||
|
clear_memory (ctlr ? &memory [020] : &memory [010], 8);
|
||||||
|
if (! (drum_op & DRUM_READ_SYSDATA))
|
||||||
|
clear_memory (&memory[drum_memory], 1024);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Обмен сектором */
|
||||||
|
drum_nwords = 256;
|
||||||
|
drum_zone = (cmd & (DRUM_UNIT | DRUM_CYLINDER)) >> 2;
|
||||||
|
drum_sector = cmd & DRUM_SECTOR;
|
||||||
|
drum_memory = (cmd & (DRUM_PAGE | DRUM_PARAGRAF)) >> 2 | (cmd & DRUM_BLOCK) >> 8;
|
||||||
|
if (drum_dev.dctrl)
|
||||||
|
besm6_debug ("### %s МБ %c%d зона %02o сектор %d память %05o-%05o",
|
||||||
|
(drum_op & DRUM_READ) ? "чтение" : "запись",
|
||||||
|
ctlr + '1', (drum_zone >> 5 & 7), drum_zone & 037,
|
||||||
|
drum_sector & 3,
|
||||||
|
drum_memory, drum_memory + drum_nwords - 1);
|
||||||
|
if (drum_op & DRUM_READ) {
|
||||||
|
clear_memory (ctlr ? &memory [020 + drum_sector*2] :
|
||||||
|
&memory [010 + drum_sector*2], 2);
|
||||||
|
if (! (drum_op & DRUM_READ_SYSDATA))
|
||||||
|
clear_memory (&memory[drum_memory], 256);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((drum_dev.flags & DEV_DIS) || ! u->fileref) {
|
||||||
|
/* Device not attached. */
|
||||||
|
drum_fail |= 0100 >> ctlr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
drum_fail &= ~(0100 >> ctlr);
|
||||||
|
if (drum_op & DRUM_READ_OVERLAY) {
|
||||||
|
/* Not implemented. */
|
||||||
|
longjmp (cpu_halt, SCPE_NOFNC);
|
||||||
|
}
|
||||||
|
if (drum_op & DRUM_READ) {
|
||||||
|
if (drum_op & DRUM_PAGE_MODE)
|
||||||
|
drum_read (u);
|
||||||
|
else
|
||||||
|
drum_read_sector (u);
|
||||||
|
} else {
|
||||||
|
if (drum_op & DRUM_PARITY_FLAG) {
|
||||||
|
besm6_log ("### запись МБ с неправильной чётностью не реализована");
|
||||||
|
longjmp (cpu_halt, SCPE_NOFNC);
|
||||||
|
}
|
||||||
|
if (u->flags & UNIT_RO) {
|
||||||
|
/* Read only. */
|
||||||
|
longjmp (cpu_halt, SCPE_RO);
|
||||||
|
}
|
||||||
|
if (drum_op & DRUM_PAGE_MODE)
|
||||||
|
drum_write (u);
|
||||||
|
else
|
||||||
|
drum_write_sector (u);
|
||||||
|
}
|
||||||
|
/*if (drum_dev.dctrl && sim_log)
|
||||||
|
log_io (u);*/
|
||||||
|
|
||||||
|
/* Гасим главный регистр прерываний. */
|
||||||
|
if (u == &drum_unit[0])
|
||||||
|
GRP &= ~GRP_DRUM1_FREE;
|
||||||
|
else
|
||||||
|
GRP &= ~GRP_DRUM2_FREE;
|
||||||
|
|
||||||
|
/* Ждём события от устройства.
|
||||||
|
* Согласно данным из книжки Мазного Г.Л.,
|
||||||
|
* даём 20 мсек на обмен, или 200 тыс.тактов. */
|
||||||
|
/*sim_activate (u, 20*MSEC);*/
|
||||||
|
sim_activate (u, 20*USEC); /* Ускорим для отладки. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Событие: закончен обмен с МБ.
|
||||||
|
* Устанавливаем флаг прерывания.
|
||||||
|
*/
|
||||||
|
t_stat drum_event (UNIT *u)
|
||||||
|
{
|
||||||
|
if (u == &drum_unit[0])
|
||||||
|
GRP |= GRP_DRUM1_FREE;
|
||||||
|
else
|
||||||
|
GRP |= GRP_DRUM2_FREE;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Опрос ошибок обмена командой 033 4035.
|
||||||
|
*/
|
||||||
|
int drum_errors ()
|
||||||
|
{
|
||||||
|
return drum_fail;
|
||||||
|
}
|
653
BESM6/besm6_mmu.c
Normal file
653
BESM6/besm6_mmu.c
Normal file
|
@ -0,0 +1,653 @@
|
||||||
|
/*
|
||||||
|
* besm6_mmu.c: BESM-6 fast write cache and TLB registers
|
||||||
|
*(стойка БРУС)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MMU data structures
|
||||||
|
*
|
||||||
|
* mmu_dev MMU device descriptor
|
||||||
|
* mmu_unit MMU unit descriptor
|
||||||
|
* mmu_reg MMU register list
|
||||||
|
*/
|
||||||
|
UNIT mmu_unit = {
|
||||||
|
UDATA (NULL, UNIT_FIX, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
t_value BRZ[8];
|
||||||
|
uint32 BAZ[8], TABST, RZ, OLDEST, FLUSH;
|
||||||
|
|
||||||
|
t_value BRS[4];
|
||||||
|
uint32 BAS[4];
|
||||||
|
uint32 BRSLRU;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 64-битные регистры RP0-RP7 - для отображения регистров приписки,
|
||||||
|
* группами по 4 ради компактности, 12 бит на страницу.
|
||||||
|
* TLB0-TLB31 - постраничные регистры приписки, копии RPi.
|
||||||
|
* Обращение к памяти должно вестись через TLBi.
|
||||||
|
*/
|
||||||
|
t_value RP[8];
|
||||||
|
uint32 TLB[32];
|
||||||
|
|
||||||
|
unsigned iintr_data; /* protected page number or parity check location */
|
||||||
|
|
||||||
|
t_value pult[8];
|
||||||
|
|
||||||
|
REG mmu_reg[] = {
|
||||||
|
{ "БРЗ0", &BRZ[0], 8, 50, 0, 1, NULL, NULL, REG_VMIO}, /* Буферные регистры записи */
|
||||||
|
{ "БРЗ1", &BRZ[1], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРЗ2", &BRZ[2], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРЗ3", &BRZ[3], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРЗ4", &BRZ[4], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРЗ5", &BRZ[5], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРЗ6", &BRZ[6], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРЗ7", &BRZ[7], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БАЗ0", &BAZ[0], 8, 16, 0, 1 }, /* Буферные адреса записи */
|
||||||
|
{ "БАЗ1", &BAZ[1], 8, 16, 0, 1 },
|
||||||
|
{ "БАЗ2", &BAZ[2], 8, 16, 0, 1 },
|
||||||
|
{ "БАЗ3", &BAZ[3], 8, 16, 0, 1 },
|
||||||
|
{ "БАЗ4", &BAZ[4], 8, 16, 0, 1 },
|
||||||
|
{ "БАЗ5", &BAZ[5], 8, 16, 0, 1 },
|
||||||
|
{ "БАЗ6", &BAZ[6], 8, 16, 0, 1 },
|
||||||
|
{ "БАЗ7", &BAZ[7], 8, 16, 0, 1 },
|
||||||
|
{ "ТАБСТ", &TABST, 8, 28, 0, 1, NULL, NULL, REG_HIDDEN },/* Таблица старшинства БРЗ */
|
||||||
|
{ "ЗпТР", &FLUSH, 8, 4, 0, 1, NULL, NULL, REG_HIDDEN },/* Признак выталкивания БРЗ */
|
||||||
|
{ "Старш", &OLDEST, 8, 3, 0, 1 }, /* Номер вытолкнутого БРЗ */
|
||||||
|
{ "РП0", &RP[0], 8, 48, 0, 1, NULL, NULL, REG_VMIO}, /* Регистры приписки, по 12 бит */
|
||||||
|
{ "РП1", &RP[1], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РП2", &RP[2], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РП3", &RP[3], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РП4", &RP[4], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РП5", &RP[5], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РП6", &RP[6], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РП7", &RP[7], 8, 48, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "РЗ", &RZ, 8, 32, 0, 1 }, /* Регистр защиты */
|
||||||
|
{ "ТР1", &pult[1], 8, 50, 0, 1, NULL, NULL, REG_VMIO}, /* Тумблерные регистры */
|
||||||
|
{ "ТР2", &pult[2], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "ТР3", &pult[3], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "ТР4", &pult[4], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "ТР5", &pult[5], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "ТР6", &pult[6], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "ТР7", &pult[7], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРС0", &BRS[0], 8, 50, 0, 1, NULL, NULL, REG_VMIO}, /* Буферные регистры слов */
|
||||||
|
{ "БРС1", &BRS[1], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРС2", &BRS[2], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БРС3", &BRS[3], 8, 50, 0, 1, NULL, NULL, REG_VMIO},
|
||||||
|
{ "БАС0", &BAS[0], 8, 16, 0, 1 }, /* Буферные адреса слов */
|
||||||
|
{ "БАС1", &BAS[1], 8, 16, 0, 1 },
|
||||||
|
{ "БАС2", &BAS[2], 8, 16, 0, 1 },
|
||||||
|
{ "БАС3", &BAS[3], 8, 16, 0, 1 },
|
||||||
|
{ "БРСст", &BRSLRU, 8, 6, 0, 1, NULL, NULL, REG_HIDDEN},
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CACHE_ENB 1
|
||||||
|
|
||||||
|
MTAB mmu_mod[] = {
|
||||||
|
{ 1, 0, "NOCACHE", "NOCACHE" },
|
||||||
|
{ 1, 1, "CACHE", "CACHE" },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
t_stat mmu_reset (DEVICE *dptr);
|
||||||
|
|
||||||
|
t_stat mmu_examine (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
|
||||||
|
{
|
||||||
|
mmu_print_brz();
|
||||||
|
return SCPE_NOFNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEVICE mmu_dev = {
|
||||||
|
"MMU", &mmu_unit, mmu_reg, mmu_mod,
|
||||||
|
1, 8, 3, 1, 8, 50,
|
||||||
|
&mmu_examine, NULL, &mmu_reset,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
DEV_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset routine
|
||||||
|
*/
|
||||||
|
t_stat mmu_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
BRZ[i] = RP[i] = BAZ[i] = 0;
|
||||||
|
}
|
||||||
|
TABST = 0;
|
||||||
|
OLDEST = 0;
|
||||||
|
FLUSH = 0;
|
||||||
|
RZ = 0;
|
||||||
|
/*
|
||||||
|
* Front panel switches survive the reset
|
||||||
|
*/
|
||||||
|
sim_cancel (&mmu_unit);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define loses_to_all(i) ((TABST & win_mask[i]) == 0 && \
|
||||||
|
(TABST & lose_mask[i]) == lose_mask[i])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* N wins over M if the bit is set
|
||||||
|
* M=1 2 3 4 5 6 7
|
||||||
|
* N -------------------------
|
||||||
|
* 0| 0 1 2 3 4 5 6
|
||||||
|
* 1| 7 8 9 10 11 12
|
||||||
|
* 2| 13 14 15 16 17
|
||||||
|
* 3| 18 19 20 21
|
||||||
|
* 4| 22 23 24
|
||||||
|
* 5| 25 26
|
||||||
|
* 6| 27
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned win_mask[8] = {
|
||||||
|
0177,
|
||||||
|
0077 << 7,
|
||||||
|
0037 << 13,
|
||||||
|
0017 << 18,
|
||||||
|
0007 << 22,
|
||||||
|
0003 << 25,
|
||||||
|
0001 << 27,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned lose_mask[8] = {
|
||||||
|
0,
|
||||||
|
1<<0,
|
||||||
|
1<<1|1<<7,
|
||||||
|
1<<2|1<<8|1<<13,
|
||||||
|
1<<3|1<<9|1<<14|1<<18,
|
||||||
|
1<<4|1<<10|1<<15|1<<19|1<<22,
|
||||||
|
1<<5|1<<11|1<<16|1<<20|1<<23|1<<25,
|
||||||
|
1<<6|1<<12|1<<17|1<<21|1<<24|1<<26|1<<27
|
||||||
|
};
|
||||||
|
|
||||||
|
#define set_wins(i) TABST = (TABST & ~lose_mask[i]) | win_mask[i]
|
||||||
|
|
||||||
|
void mmu_protection_check (int addr)
|
||||||
|
{
|
||||||
|
/* Защита блокируется в режиме супервизора для физических (!) адресов 1-7 (ТО-8) - WTF? */
|
||||||
|
int tmp_prot_disabled = (M[PSW] & PSW_PROT_DISABLE) ||
|
||||||
|
(IS_SUPERVISOR (RUU) && (M[PSW] & PSW_MMAP_DISABLE) && addr < 010);
|
||||||
|
|
||||||
|
/* Защита не заблокирована, а лист закрыт */
|
||||||
|
if (! tmp_prot_disabled && (RZ & (1 << (addr >> 10)))) {
|
||||||
|
iintr_data = addr >> 10;
|
||||||
|
if (mmu_dev.dctrl)
|
||||||
|
besm6_debug ("--- (%05o) защита числа", addr);
|
||||||
|
longjmp (cpu_halt, STOP_OPERAND_PROT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_flush (int idx)
|
||||||
|
{
|
||||||
|
int waddr = BAZ[idx];
|
||||||
|
|
||||||
|
if (! BAZ[idx]) {
|
||||||
|
/* Был пуст после сброса или выталкивания */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Вычисляем физический адрес выталкиваемого БРЗ */
|
||||||
|
waddr = (waddr > 0100000) ? (waddr - 0100000) :
|
||||||
|
(waddr & 01777) | (TLB[waddr >> 10] << 10);
|
||||||
|
memory[waddr] = BRZ[idx];
|
||||||
|
BAZ[idx] = 0;
|
||||||
|
if (sim_log && mmu_dev.dctrl) {
|
||||||
|
fprintf (sim_log, "--- (%05o) запись ", waddr);
|
||||||
|
fprint_sym (sim_log, 0, &BRZ[idx], 0, 0);
|
||||||
|
fprintf (sim_log, " из БРЗ[%d]\n", idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_update_oldest ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
if (loses_to_all(i)) {
|
||||||
|
OLDEST = i;
|
||||||
|
// fprintf(stderr, "Oldest = %d\r\n", i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mmu_match (int addr, int fail)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
if (addr == BAZ[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Разнообразные алгоритмы выталкивания БРЗ путем записи
|
||||||
|
* по адресам пультовых регистров. Тест УУ проходит дальше всего
|
||||||
|
* с mmu_flush_by_age().
|
||||||
|
*/
|
||||||
|
void mmu_flush_by_age()
|
||||||
|
{
|
||||||
|
switch (FLUSH) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
|
||||||
|
set_wins (OLDEST);
|
||||||
|
mmu_update_oldest ();
|
||||||
|
mmu_flush (OLDEST);
|
||||||
|
if (FLUSH == 7) {
|
||||||
|
TABST = 0;
|
||||||
|
OLDEST = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++FLUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_flush_by_number()
|
||||||
|
{
|
||||||
|
switch (FLUSH) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
|
||||||
|
mmu_flush (FLUSH-1);
|
||||||
|
set_wins (FLUSH-1);
|
||||||
|
if (FLUSH-1 == OLDEST)
|
||||||
|
mmu_update_oldest ();
|
||||||
|
if (FLUSH == 7) {
|
||||||
|
TABST = 0;
|
||||||
|
OLDEST = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++FLUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Запись слова в память
|
||||||
|
*/
|
||||||
|
void mmu_store (int addr, t_value val)
|
||||||
|
{
|
||||||
|
int matching;
|
||||||
|
|
||||||
|
addr &= BITS(15);
|
||||||
|
if (addr == 0)
|
||||||
|
return;
|
||||||
|
if (sim_log && mmu_dev.dctrl) {
|
||||||
|
fprintf (sim_log, "--- (%05o) запись ", addr);
|
||||||
|
fprint_sym (sim_log, 0, &val, 0, 0);
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mmu_protection_check (addr);
|
||||||
|
|
||||||
|
/* Различаем адреса с припиской и без */
|
||||||
|
if (M[PSW] & PSW_MMAP_DISABLE)
|
||||||
|
addr |= 0100000;
|
||||||
|
|
||||||
|
/* ЗПСЧ: ЗП */
|
||||||
|
if (M[DWP] == addr && (M[PSW] & PSW_WRITE_WATCH))
|
||||||
|
longjmp(cpu_halt, STOP_STORE_ADDR_MATCH);
|
||||||
|
|
||||||
|
if (sim_brk_summ & SWMASK('W') &&
|
||||||
|
sim_brk_test (addr, SWMASK('W')))
|
||||||
|
longjmp(cpu_halt, STOP_WWATCH);
|
||||||
|
|
||||||
|
if (!(mmu_unit.flags & CACHE_ENB)) {
|
||||||
|
static int roundrobin;
|
||||||
|
int faked = (++roundrobin ^ addr ^ val) & 7;
|
||||||
|
|
||||||
|
if (addr > 0100000 && addr < 0100010)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BRZ[faked] = SET_CONVOL (val, RUU ^ CONVOL_INSN);
|
||||||
|
BAZ[faked] = addr;
|
||||||
|
mmu_flush (faked);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Запись в тумблерные регистры - выталкивание БРЗ */
|
||||||
|
if (addr > 0100000 && addr < 0100010) {
|
||||||
|
mmu_flush_by_age();
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
FLUSH = 0;
|
||||||
|
|
||||||
|
matching = mmu_match(addr, OLDEST);
|
||||||
|
|
||||||
|
BRZ[matching] = SET_CONVOL (val, RUU ^ CONVOL_INSN);
|
||||||
|
BAZ[matching] = addr;
|
||||||
|
set_wins (matching);
|
||||||
|
|
||||||
|
if (matching == OLDEST) {
|
||||||
|
mmu_update_oldest ();
|
||||||
|
mmu_flush (OLDEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t_value mmu_memaccess (int addr)
|
||||||
|
{
|
||||||
|
t_value val;
|
||||||
|
|
||||||
|
/* Вычисляем физический адрес слова */
|
||||||
|
addr = (addr > 0100000) ? (addr - 0100000) :
|
||||||
|
(addr & 01777) | (TLB[addr >> 10] << 10);
|
||||||
|
if (addr >= 010) {
|
||||||
|
/* Из памяти */
|
||||||
|
val = memory[addr];
|
||||||
|
} else {
|
||||||
|
/* С тумблерных регистров */
|
||||||
|
if (mmu_dev.dctrl)
|
||||||
|
besm6_debug("--- (%05o) чтение ТР%o", PC, addr);
|
||||||
|
val = pult[addr];
|
||||||
|
}
|
||||||
|
if (sim_log && (mmu_dev.dctrl || (cpu_dev.dctrl && sim_deb))) {
|
||||||
|
fprintf (sim_log, "--- (%05o) чтение ", addr & BITS(15));
|
||||||
|
fprint_sym (sim_log, 0, &val, 0, 0);
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* На тумблерных регистрах контроля числа не бывает */
|
||||||
|
if (addr >= 010 && ! IS_NUMBER (val)) {
|
||||||
|
iintr_data = addr & 7;
|
||||||
|
besm6_debug ("--- (%05o) контроль числа", addr);
|
||||||
|
longjmp (cpu_halt, STOP_RAM_CHECK);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Чтение операнда
|
||||||
|
*/
|
||||||
|
t_value mmu_load (int addr)
|
||||||
|
{
|
||||||
|
int matching = -1;
|
||||||
|
t_value val;
|
||||||
|
|
||||||
|
addr &= BITS(15);
|
||||||
|
if (addr == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mmu_protection_check (addr);
|
||||||
|
|
||||||
|
/* Различаем адреса с припиской и без */
|
||||||
|
if (M[PSW] & PSW_MMAP_DISABLE)
|
||||||
|
addr |= 0100000;
|
||||||
|
|
||||||
|
/* ЗПСЧ: СЧ */
|
||||||
|
if (M[DWP] == addr && !(M[PSW] & PSW_WRITE_WATCH))
|
||||||
|
longjmp(cpu_halt, STOP_LOAD_ADDR_MATCH);
|
||||||
|
|
||||||
|
if (sim_brk_summ & SWMASK('R') &&
|
||||||
|
sim_brk_test (addr, SWMASK('R')))
|
||||||
|
longjmp(cpu_halt, STOP_RWATCH);
|
||||||
|
|
||||||
|
if (!(mmu_unit.flags & CACHE_ENB)) {
|
||||||
|
return mmu_memaccess (addr) & BITS48;
|
||||||
|
}
|
||||||
|
|
||||||
|
matching = mmu_match(addr, -1);
|
||||||
|
|
||||||
|
if (matching == -1) {
|
||||||
|
val = mmu_memaccess (addr);
|
||||||
|
} else {
|
||||||
|
/* старшинство обновляется, только если оно не затрагивает
|
||||||
|
* старший БРЗ (ТО-2).
|
||||||
|
*/
|
||||||
|
if (matching != OLDEST)
|
||||||
|
set_wins (matching);
|
||||||
|
val = BRZ[matching];
|
||||||
|
if (sim_log && (mmu_dev.dctrl || (cpu_dev.dctrl && sim_deb))) {
|
||||||
|
fprintf (sim_log, "--- (%05o) чтение ", addr & BITS(15));
|
||||||
|
fprint_sym (sim_log, 0, &val, 0, 0);
|
||||||
|
fprintf (sim_log, " из БРЗ\n");
|
||||||
|
}
|
||||||
|
if (! IS_NUMBER (val)) {
|
||||||
|
iintr_data = matching;
|
||||||
|
besm6_debug ("--- (%05o) контроль числа БРЗ", addr);
|
||||||
|
longjmp (cpu_halt, STOP_CACHE_CHECK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val & BITS48;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A little BRS LRU table */
|
||||||
|
#define brs_loses_to_all(i) ((BRSLRU & brs_win_mask[i]) == 0 && \
|
||||||
|
(BRSLRU & brs_lose_mask[i]) == brs_lose_mask[i])
|
||||||
|
|
||||||
|
/*
|
||||||
|
* N wins over M if the bit is set
|
||||||
|
* M=1 2 3
|
||||||
|
* N ---------
|
||||||
|
* 0| 0 1 2
|
||||||
|
* 1| 3 4
|
||||||
|
* 2| 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned brs_win_mask[4] = {
|
||||||
|
07,
|
||||||
|
03 << 3,
|
||||||
|
01 << 5,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned brs_lose_mask[8] = {
|
||||||
|
0,
|
||||||
|
1<<0,
|
||||||
|
1<<1|1<<3,
|
||||||
|
1<<2|1<<4|1<<5
|
||||||
|
};
|
||||||
|
|
||||||
|
#define brs_set_wins(i) BRSLRU = (BRSLRU & ~brs_lose_mask[i]) | brs_win_mask[i]
|
||||||
|
|
||||||
|
void mmu_fetch_check (int addr)
|
||||||
|
{
|
||||||
|
/* В режиме супервизора защиты нет */
|
||||||
|
if (! IS_SUPERVISOR(RUU)) {
|
||||||
|
int page = TLB[addr >> 10];
|
||||||
|
/*
|
||||||
|
* Для команд в режиме пользователя признак защиты -
|
||||||
|
* 0 в регистре приписки.
|
||||||
|
*/
|
||||||
|
if (page == 0) {
|
||||||
|
iintr_data = addr >> 10;
|
||||||
|
if (mmu_dev.dctrl)
|
||||||
|
besm6_debug ("--- (%05o) защита команды", addr);
|
||||||
|
longjmp (cpu_halt, STOP_INSN_PROT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Предвыборка команды на БРС
|
||||||
|
*/
|
||||||
|
t_value mmu_prefetch (int addr, int actual)
|
||||||
|
{
|
||||||
|
t_value val;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (mmu_unit.flags & CACHE_ENB) {
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (BAS[i] == addr) {
|
||||||
|
if (actual) {
|
||||||
|
brs_set_wins (i);
|
||||||
|
}
|
||||||
|
return BRS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
if (brs_loses_to_all (i)) {
|
||||||
|
BAS[i] = addr;
|
||||||
|
if (actual) {
|
||||||
|
brs_set_wins (i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!actual) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/* Чтобы лампочки мигали */
|
||||||
|
i = addr & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr < 0100000) {
|
||||||
|
int page = TLB[addr >> 10];
|
||||||
|
|
||||||
|
/* Вычисляем физический адрес слова */
|
||||||
|
addr = (addr & 01777) | (page << 10);
|
||||||
|
} else {
|
||||||
|
addr = addr & BITS(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr < 010)
|
||||||
|
val = pult[addr];
|
||||||
|
else
|
||||||
|
val = memory[addr];
|
||||||
|
BRS[i] = val;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выборка команды
|
||||||
|
*/
|
||||||
|
t_value mmu_fetch (int addr)
|
||||||
|
{
|
||||||
|
t_value val;
|
||||||
|
|
||||||
|
if (addr == 0) {
|
||||||
|
if (mmu_dev.dctrl)
|
||||||
|
besm6_debug ("--- передача управления на 0");
|
||||||
|
longjmp (cpu_halt, STOP_INSN_CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
mmu_fetch_check(addr);
|
||||||
|
|
||||||
|
/* Различаем адреса с припиской и без */
|
||||||
|
if (IS_SUPERVISOR (RUU))
|
||||||
|
addr |= 0100000;
|
||||||
|
|
||||||
|
/* КРА */
|
||||||
|
if (M[IBP] == addr)
|
||||||
|
longjmp(cpu_halt, STOP_INSN_ADDR_MATCH);
|
||||||
|
|
||||||
|
val = mmu_prefetch(addr, 1);
|
||||||
|
|
||||||
|
if (sim_log && mmu_dev.dctrl) {
|
||||||
|
fprintf (sim_log, "--- (%05o) выборка ", addr);
|
||||||
|
fprint_sym (sim_log, 0, &val, 0, SWMASK ('I'));
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Тумблерные регистры пока только с командной сверткой */
|
||||||
|
if (addr >= 010 && ! IS_INSN (val)) {
|
||||||
|
besm6_debug ("--- (%05o) контроль команды", addr);
|
||||||
|
longjmp (cpu_halt, STOP_INSN_CHECK);
|
||||||
|
}
|
||||||
|
return val & BITS48;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_setrp (int idx, t_value val)
|
||||||
|
{
|
||||||
|
uint32 p0, p1, p2, p3;
|
||||||
|
const uint32 mask = (MEMSIZE >> 10) - 1;
|
||||||
|
|
||||||
|
/* Младшие 5 разрядов 4-х регистров приписки упакованы
|
||||||
|
* по 5 в 1-20 рр, 6-е разряды - в 29-32 рр, 7-е разряды - в 33-36 рр и т.п.
|
||||||
|
*/
|
||||||
|
p0 = (val & 037) | (((val>>28) & 1) << 5) | (((val>>32) & 1) << 6) |
|
||||||
|
(((val>>36) & 1) << 7) | (((val>>40) & 1) << 8) | (((val>>44) & 1) << 9);
|
||||||
|
p1 = ((val>>5) & 037) | (((val>>29) & 1) << 5) | (((val>>33) & 1) << 6) |
|
||||||
|
(((val>>37) & 1) << 7) | (((val>>41) & 1) << 8) | (((val>>45) & 1) << 9);
|
||||||
|
p2 = ((val>>10) & 037) | (((val>>30) & 1) << 5) | (((val>>34) & 1) << 6) |
|
||||||
|
(((val>>38) & 1) << 7) | (((val>>42) & 1) << 8) | (((val>>46) & 1) << 9);
|
||||||
|
p3 = ((val>>15) & 037) | (((val>>31) & 1) << 5) | (((val>>35) & 1) << 6) |
|
||||||
|
(((val>>39) & 1) << 7) | (((val>>43) & 1) << 8) | (((val>>47) & 1) << 9);
|
||||||
|
|
||||||
|
p0 &= mask;
|
||||||
|
p1 &= mask;
|
||||||
|
p2 &= mask;
|
||||||
|
p3 &= mask;
|
||||||
|
|
||||||
|
RP[idx] = p0 | p1 << 12 | p2 << 24 | (t_value) p3 << 36;
|
||||||
|
TLB[idx*4] = p0;
|
||||||
|
TLB[idx*4+1] = p1;
|
||||||
|
TLB[idx*4+2] = p2;
|
||||||
|
TLB[idx*4+3] = p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_setup ()
|
||||||
|
{
|
||||||
|
const uint32 mask = (MEMSIZE >> 10) - 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Перепись РПi в TLBj. */
|
||||||
|
for (i=0; i<8; ++i) {
|
||||||
|
TLB[i*4] = RP[i] & mask;
|
||||||
|
TLB[i*4+1] = RP[i] >> 12 & mask;
|
||||||
|
TLB[i*4+2] = RP[i] >> 24 & mask;
|
||||||
|
TLB[i*4+3] = RP[i] >> 36 & mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_setprotection (int idx, t_value val)
|
||||||
|
{
|
||||||
|
/* Разряды сумматора, записываемые в регистр защиты - 21-28 */
|
||||||
|
int mask = 0xff << (idx * 8);
|
||||||
|
val = ((val >> 20) & 0xff) << (idx * 8);
|
||||||
|
RZ = (uint32)((RZ & ~mask) | val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_setcache (int idx, t_value val)
|
||||||
|
{
|
||||||
|
BRZ[idx] = SET_CONVOL (val, RUU ^ CONVOL_INSN);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_value mmu_getcache (int idx)
|
||||||
|
{
|
||||||
|
return BRZ[idx] & BITS48;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_print_brz ()
|
||||||
|
{
|
||||||
|
int i, k;
|
||||||
|
|
||||||
|
for (i=7; i>=0; --i) {
|
||||||
|
besm6_log_cont ("БРЗ [%d] = '", i);
|
||||||
|
for (k=47; k>=0; --k)
|
||||||
|
besm6_log_cont ("%c", (BRZ[i] >> k & 1) ? '*' : ' ');
|
||||||
|
besm6_log ("'");
|
||||||
|
}
|
||||||
|
}
|
550
BESM6/besm6_panel.c
Normal file
550
BESM6/besm6_panel.c
Normal file
|
@ -0,0 +1,550 @@
|
||||||
|
/*
|
||||||
|
* Panel of BESM-6, displayed as a graphics window.
|
||||||
|
* Using libSDL for graphics and libSDL_ttf for fonts.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Serge Vakulenko
|
||||||
|
* Copyright (c) 2014, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (HAVE_LIBSDL)
|
||||||
|
#if !defined (FONTFILE)
|
||||||
|
#include "besm6_panel_font.h"
|
||||||
|
#endif /* !defined (FONTFILE) */
|
||||||
|
#if !defined (FONTFILE)
|
||||||
|
#undef HAVE_LIBSDL
|
||||||
|
#endif /* !defined (FONTFILE) */
|
||||||
|
#endif /* defined (HAVE_LIBSDL) */
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSDL
|
||||||
|
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use a 640x480 window with 32 bit pixels.
|
||||||
|
*/
|
||||||
|
#define WIDTH 800
|
||||||
|
#define HEIGHT 400
|
||||||
|
#define DEPTH 32
|
||||||
|
|
||||||
|
#define STEPX 14
|
||||||
|
#define STEPY 16
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_ttf.h>
|
||||||
|
|
||||||
|
#define _QUOTE(x) #x
|
||||||
|
#define QUOTE(x) _QUOTE(x)
|
||||||
|
|
||||||
|
/* Data and functions that don't depend on SDL version */
|
||||||
|
static TTF_Font *font_big;
|
||||||
|
static TTF_Font *font_small;
|
||||||
|
static SDL_Color foreground;
|
||||||
|
static SDL_Color background;
|
||||||
|
static const SDL_Color white = { 255, 255, 255 };
|
||||||
|
static const SDL_Color black = { 0, 0, 0 };
|
||||||
|
static const SDL_Color cyan = { 0, 128, 128 };
|
||||||
|
static const SDL_Color grey = { 64, 64, 64 };
|
||||||
|
static t_value old_BRZ [8], old_GRP [2];
|
||||||
|
static t_value old_M [NREGS];
|
||||||
|
|
||||||
|
static const int regnum[] = {
|
||||||
|
013, 012, 011, 010, 7, 6, 5, 4,
|
||||||
|
027, 016, 015, 014, 3, 2, 1, 020,
|
||||||
|
};
|
||||||
|
|
||||||
|
static SDL_Surface *screen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing antialiased text in UTF-8 encoding.
|
||||||
|
* The halign parameter controls horizontal alignment.
|
||||||
|
* Foreground/background colors are taken from global variables.
|
||||||
|
*/
|
||||||
|
static void render_utf8 (TTF_Font *font, int x, int y, int halign, char *message)
|
||||||
|
{
|
||||||
|
SDL_Surface *text;
|
||||||
|
SDL_Rect area;
|
||||||
|
|
||||||
|
/* Build image from text */
|
||||||
|
text = TTF_RenderUTF8_Shaded (font, message, foreground, background);
|
||||||
|
|
||||||
|
area.x = x;
|
||||||
|
if (halign < 0)
|
||||||
|
area.x -= text->w; /* align left */
|
||||||
|
else if (halign == 0)
|
||||||
|
area.x -= text->w / 2; /* center */
|
||||||
|
area.y = y;
|
||||||
|
area.w = text->w;
|
||||||
|
area.h = text->h;
|
||||||
|
|
||||||
|
/* Put text image to screen */
|
||||||
|
SDL_BlitSurface (text, 0, screen, &area);
|
||||||
|
SDL_FreeSurface (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_Surface *sprite_from_data (int width, int height,
|
||||||
|
const unsigned char *data)
|
||||||
|
{
|
||||||
|
SDL_Surface *sprite;
|
||||||
|
unsigned *s, r, g, b;
|
||||||
|
int y, x;
|
||||||
|
|
||||||
|
sprite = SDL_CreateRGBSurface (SDL_SWSURFACE,
|
||||||
|
width, height, DEPTH, 0, 0, 0, 0);
|
||||||
|
/*
|
||||||
|
SDL_Surface *optimized = SDL_DisplayFormat (sprite);
|
||||||
|
SDL_FreeSurface (sprite);
|
||||||
|
sprite = optimized;
|
||||||
|
*/
|
||||||
|
SDL_LockSurface (sprite);
|
||||||
|
for (y=0; y<height; ++y) {
|
||||||
|
s = (unsigned*) ((char*)sprite->pixels + y * sprite->pitch);
|
||||||
|
for (x=0; x<width; ++x) {
|
||||||
|
r = *data++;
|
||||||
|
g = *data++;
|
||||||
|
b = *data++;
|
||||||
|
*s++ = SDL_MapRGB (sprite->format, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_UnlockSurface (sprite);
|
||||||
|
return sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing a neon light.
|
||||||
|
*/
|
||||||
|
static void draw_lamp (int left, int top, int on)
|
||||||
|
{
|
||||||
|
/* Images created by GIMP: save as C file without alpha channel. */
|
||||||
|
static const int lamp_width = 12;
|
||||||
|
static const int lamp_height = 12;
|
||||||
|
static const unsigned char lamp_on [12 * 12 * 3 + 1] =
|
||||||
|
"\0\0\0\0\0\0\0\0\0\13\2\2-\14\14e\31\31e\31\31-\14\14\13\2\2\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0D\20\20\313,,\377??\377CC\377CC\377DD\31333D\21\21\0\0"
|
||||||
|
"\0\0\0\0\0\0\0D\20\20\357LL\377\243\243\376~~\37699\376@@\376@@\377AA\357"
|
||||||
|
"<<D\21\21\0\0\0\13\2\2\313,,\377\243\243\377\373\373\377\356\356\377NN\377"
|
||||||
|
">>\377@@\377@@\377AA\31333\13\2\2-\14\14\377??\376~~\377\356\356\377\321"
|
||||||
|
"\321\377<<\377??\377@@\377@@\376@@\377DD-\14\14e\31\31\377CC\37699\377NN"
|
||||||
|
"\377<<\377??\377@@\377@@\377@@\376??\377CCe\31\31e\31\31\377CC\376@@\377"
|
||||||
|
">>\377??\377@@\377@@\377@@\377@@\376??\377CCe\31\31-\14\14\377DD\376@@\377"
|
||||||
|
"@@\377@@\377@@\377@@\377@@\377@@\376@@\377DD-\14\14\13\2\2\31333\377AA\377"
|
||||||
|
"@@\377@@\377@@\377@@\377@@\377@@\377AA\31333\13\2\2\0\0\0D\21\21\357<<\377"
|
||||||
|
"AA\376@@\376??\376??\376@@\377AA\357<<D\21\21\0\0\0\0\0\0\0\0\0D\21\21\313"
|
||||||
|
"33\377DD\377CC\377CC\377DD\31333D\21\21\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13"
|
||||||
|
"\2\2-\14\14e\31\31e\31\31-\14\14\13\2\2\0\0\0\0\0\0\0\0\0";
|
||||||
|
static const unsigned char lamp_off [12 * 12 * 3 + 1] =
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\14\2\2\14\2\2\14\2\2\14\2\2\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\25\5\5A\21\21h\32\32c\30\30c\30\30h\32\32A\21\21\25\5\5"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\25\5\5\\\30\30""8\16\16\0\0\0\0\0\0\0\0\0\0\0\0""8\16"
|
||||||
|
"\16\\\30\30\25\5\5\0\0\0\0\0\0A\21\21""8\16\16\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0""8\16\16A\21\21\0\0\0\14\2\2h\32\32\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0h\32\32\14\2\2\14\2\2c\30\30\0\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0c\30\30\14\2\2\14\2\2c\30\30\0\0\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0c\30\30\14\2\2\14\2\2h\32\32\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0h\32\32\14\2\2\0\0\0A\21\21""8\16\16\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""8\16\16A\21\21\0\0\0\0\0\0\25\5\5\\\30"
|
||||||
|
"\30""8\16\16\0\0\0\0\0\0\0\0\0\0\0\0""8\16\16\\\30\30\25\5\5\0\0\0\0\0\0"
|
||||||
|
"\0\0\0\25\5\5A\21\21h\32\32c\30\30c\30\30h\32\32A\21\21\25\5\5\0\0\0\0\0"
|
||||||
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\14\2\2\14\2\2\14\2\2\14\2\2\0\0\0\0\0\0\0\0\0"
|
||||||
|
"\0\0\0";
|
||||||
|
static SDL_Surface *sprite_on, *sprite_off;
|
||||||
|
SDL_Rect area;
|
||||||
|
|
||||||
|
if (! sprite_on) {
|
||||||
|
sprite_on = sprite_from_data (lamp_width, lamp_height,
|
||||||
|
lamp_on);
|
||||||
|
}
|
||||||
|
if (! sprite_off) {
|
||||||
|
sprite_off = sprite_from_data (lamp_width, lamp_height,
|
||||||
|
lamp_off);
|
||||||
|
}
|
||||||
|
area.x = left;
|
||||||
|
area.y = top;
|
||||||
|
area.w = lamp_width;
|
||||||
|
area.h = lamp_height;
|
||||||
|
SDL_BlitSurface (on ? sprite_on : sprite_off, 0, screen, &area);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing index (modifier) registers. They form two groups.
|
||||||
|
*/
|
||||||
|
static void draw_modifiers_periodic (int group, int left, int top)
|
||||||
|
{
|
||||||
|
int x, y, reg, val;
|
||||||
|
|
||||||
|
for (y=0; y<8; ++y) {
|
||||||
|
reg = regnum [y + group*8];
|
||||||
|
val = M [reg];
|
||||||
|
if (val == old_M [reg])
|
||||||
|
continue;
|
||||||
|
old_M [reg] = val;
|
||||||
|
for (x=0; x<15; ++x) {
|
||||||
|
draw_lamp (left+76 + x*STEPX, top+28 + y*STEPY, val >> (14-x) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing the main interrupt register and its mask.
|
||||||
|
*/
|
||||||
|
static void draw_grp_periodic (int top)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
t_value val;
|
||||||
|
|
||||||
|
for (y=0; y<2; ++y) {
|
||||||
|
val = y ? MGRP : GRP;
|
||||||
|
if (val == old_GRP [y])
|
||||||
|
continue;
|
||||||
|
old_GRP [y] = val;
|
||||||
|
for (x=0; x<48; ++x) {
|
||||||
|
draw_lamp (100 + x*STEPX, top+28 + y*STEPY, val >> (47-x) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing the data cache registers.
|
||||||
|
*/
|
||||||
|
static void draw_brz_periodic (int top)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
t_value val;
|
||||||
|
|
||||||
|
for (y=0; y<8; ++y) {
|
||||||
|
val = BRZ [7-y];
|
||||||
|
if (val == old_BRZ [7-y])
|
||||||
|
continue;
|
||||||
|
old_BRZ [7-y] = val;
|
||||||
|
for (x=0; x<48; ++x) {
|
||||||
|
draw_lamp (100 + x*STEPX, top+28 + y*STEPY, val >> (47-x) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing the static part of the modifier register area.
|
||||||
|
*/
|
||||||
|
static void draw_modifiers_static (int group, int left, int top)
|
||||||
|
{
|
||||||
|
int x, y, color, reg;
|
||||||
|
char message [40];
|
||||||
|
SDL_Rect area;
|
||||||
|
|
||||||
|
background = black;
|
||||||
|
foreground = cyan;
|
||||||
|
|
||||||
|
/* Visually separating groups of bits */
|
||||||
|
color = grey.r << 16 | grey.g << 8 | grey.b;
|
||||||
|
for (x=3; x<15; x+=3) {
|
||||||
|
area.x = left + 74 + x*STEPX;
|
||||||
|
area.y = top + 26;
|
||||||
|
area.w = 2;
|
||||||
|
area.h = 8*STEPY + 2;
|
||||||
|
SDL_FillRect (screen, &area, color);
|
||||||
|
}
|
||||||
|
/* Register names */
|
||||||
|
for (y=0; y<8; ++y) {
|
||||||
|
reg = regnum [y + group*8];
|
||||||
|
sprintf (message, "М%2o", reg);
|
||||||
|
render_utf8 (font_big, left, top + 24 + y*STEPY, 1, message);
|
||||||
|
old_M [reg] = ~0;
|
||||||
|
}
|
||||||
|
/* Bit numbers */
|
||||||
|
for (x=0; x<15; ++x) {
|
||||||
|
sprintf (message, "%d", 15-x);
|
||||||
|
render_utf8 (font_small, left+82 + x*STEPX,
|
||||||
|
(x & 1) ? top+4 : top+10, 0, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing the static part of the interrupt register area.
|
||||||
|
*/
|
||||||
|
static void draw_grp_static (int top)
|
||||||
|
{
|
||||||
|
int x, y, color;
|
||||||
|
char message [40];
|
||||||
|
SDL_Rect area;
|
||||||
|
|
||||||
|
background = black;
|
||||||
|
foreground = cyan;
|
||||||
|
|
||||||
|
/* Visually separating groups of bits */
|
||||||
|
color = grey.r << 16 | grey.g << 8 | grey.b;
|
||||||
|
for (x=3; x<48; x+=3) {
|
||||||
|
area.x = 98 + x*STEPX;
|
||||||
|
area.y = top + 26;
|
||||||
|
area.w = 2;
|
||||||
|
area.h = 2*STEPY + 2;
|
||||||
|
SDL_FillRect (screen, &area, color);
|
||||||
|
}
|
||||||
|
/* Register names */
|
||||||
|
for (y=0; y<2; ++y) {
|
||||||
|
render_utf8 (font_big, 24, top + 24 + y*STEPY, 1, y ? "МГРП" : "ГРП");
|
||||||
|
old_GRP[y] = ~0;
|
||||||
|
}
|
||||||
|
/* Bit numbers */
|
||||||
|
for (x=0; x<48; ++x) {
|
||||||
|
sprintf (message, "%d", 48-x);
|
||||||
|
render_utf8 (font_small, 106 + x*STEPX,
|
||||||
|
(x & 1) ? top+10 : top+4, 0, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing the static part of the cache register area
|
||||||
|
*/
|
||||||
|
static void draw_brz_static (int top)
|
||||||
|
{
|
||||||
|
int x, y, color;
|
||||||
|
char message [40];
|
||||||
|
SDL_Rect area;
|
||||||
|
|
||||||
|
background = black;
|
||||||
|
foreground = cyan;
|
||||||
|
|
||||||
|
/* Visually separating groups of bits */
|
||||||
|
color = grey.r << 16 | grey.g << 8 | grey.b;
|
||||||
|
for (x=3; x<48; x+=3) {
|
||||||
|
area.x = 98 + x*STEPX;
|
||||||
|
area.y = top + 26;
|
||||||
|
area.w = 2;
|
||||||
|
area.h = 8*STEPY + 2;
|
||||||
|
SDL_FillRect (screen, &area, color);
|
||||||
|
}
|
||||||
|
/* Register names */
|
||||||
|
for (y=7; y>=0; --y) {
|
||||||
|
sprintf (message, "БРЗ %d", 7-y);
|
||||||
|
render_utf8 (font_big, 24, top + 24 + y*STEPY, 1, message);
|
||||||
|
old_BRZ[y] = ~0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closing the graphical window.
|
||||||
|
*/
|
||||||
|
void besm6_close_panel (void)
|
||||||
|
{
|
||||||
|
if (! screen)
|
||||||
|
return;
|
||||||
|
TTF_Quit();
|
||||||
|
SDL_Quit();
|
||||||
|
screen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SDL_MAJOR_VERSION == 2
|
||||||
|
|
||||||
|
static SDL_Window *sdlWindow;
|
||||||
|
static SDL_Renderer *sdlRenderer;
|
||||||
|
static SDL_Texture *sdlTexture;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializing of the graphical window and the fonts.
|
||||||
|
*/
|
||||||
|
static void init_panel (void)
|
||||||
|
{
|
||||||
|
if (sim_switches & SWMASK('Q'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Initialize SDL subsystems - in this case, only video. */
|
||||||
|
if (SDL_Init (SDL_INIT_VIDEO) < 0) {
|
||||||
|
fprintf (stderr, "SDL: unable to init: %s\n",
|
||||||
|
SDL_GetError ());
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
sdlWindow = SDL_CreateWindow ("BESM-6 panel",
|
||||||
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
WIDTH, HEIGHT, 0 /* regular window */);
|
||||||
|
if (! sdlWindow) {
|
||||||
|
fprintf (stderr, "SDL: unable to set %dx%dx%d mode: %s\n",
|
||||||
|
WIDTH, HEIGHT, DEPTH, SDL_GetError ());
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);
|
||||||
|
/* Make black background */
|
||||||
|
SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255);
|
||||||
|
SDL_RenderClear(sdlRenderer);
|
||||||
|
|
||||||
|
/* Initialize the TTF library */
|
||||||
|
if (TTF_Init() < 0) {
|
||||||
|
fprintf (stderr, "SDL: couldn't initialize TTF: %s\n",
|
||||||
|
SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the font file with the requested point size */
|
||||||
|
font_big = TTF_OpenFont (QUOTE(FONTFILE), 16);
|
||||||
|
font_small = TTF_OpenFont (QUOTE(FONTFILE), 9);
|
||||||
|
if (! font_big || ! font_small) {
|
||||||
|
fprintf(stderr, "SDL: couldn't load font %s: %s\n",
|
||||||
|
QUOTE(FONTFILE), SDL_GetError());
|
||||||
|
besm6_close_panel();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
atexit (besm6_close_panel);
|
||||||
|
|
||||||
|
screen = SDL_CreateRGBSurface(0, WIDTH, HEIGHT, 32,
|
||||||
|
0x00FF0000,
|
||||||
|
0x0000FF00,
|
||||||
|
0x000000FF,
|
||||||
|
0xFF000000);
|
||||||
|
|
||||||
|
sdlTexture = SDL_CreateTexture(sdlRenderer,
|
||||||
|
SDL_PIXELFORMAT_ARGB8888,
|
||||||
|
SDL_TEXTUREACCESS_STATIC,
|
||||||
|
WIDTH, HEIGHT);
|
||||||
|
|
||||||
|
/* Drawing the static part of the BESM-6 panel */
|
||||||
|
draw_modifiers_static (0, 24, 10);
|
||||||
|
draw_modifiers_static (1, 400, 10);
|
||||||
|
draw_grp_static (180);
|
||||||
|
draw_brz_static (230);
|
||||||
|
|
||||||
|
/* Tell SDL to update the whole screen */
|
||||||
|
SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch);
|
||||||
|
SDL_RenderClear(sdlRenderer);
|
||||||
|
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
|
||||||
|
SDL_RenderPresent (sdlRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*sim_vm_init)() = init_panel;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Refreshing the window.
|
||||||
|
*/
|
||||||
|
void besm6_draw_panel (void)
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
if (! screen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Do the blinkenlights */
|
||||||
|
draw_modifiers_periodic (0, 24, 10);
|
||||||
|
draw_modifiers_periodic (1, 400, 10);
|
||||||
|
draw_grp_periodic (180);
|
||||||
|
draw_brz_periodic (230);
|
||||||
|
|
||||||
|
/* Tell SDL to update the whole screen */
|
||||||
|
SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch);
|
||||||
|
SDL_RenderClear(sdlRenderer);
|
||||||
|
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
|
||||||
|
SDL_RenderPresent (sdlRenderer);
|
||||||
|
|
||||||
|
/* Exit SIMH when window closed.*/
|
||||||
|
if (SDL_PollEvent (&event) && event.type == SDL_QUIT)
|
||||||
|
longjmp (cpu_halt, SCPE_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializing of the graphical window and the fonts.
|
||||||
|
*/
|
||||||
|
static void init_panel (void)
|
||||||
|
{
|
||||||
|
if (sim_switches & SWMASK('Q'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Initialize SDL subsystems - in this case, only video. */
|
||||||
|
if (SDL_Init (SDL_INIT_VIDEO) < 0) {
|
||||||
|
fprintf (stderr, "SDL: unable to init: %s\n",
|
||||||
|
SDL_GetError ());
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
screen = SDL_SetVideoMode (WIDTH, HEIGHT, DEPTH, SDL_SWSURFACE);
|
||||||
|
if (! screen) {
|
||||||
|
fprintf (stderr, "SDL: unable to set %dx%dx%d mode: %s\n",
|
||||||
|
WIDTH, HEIGHT, DEPTH, SDL_GetError ());
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the TTF library */
|
||||||
|
if (TTF_Init() < 0) {
|
||||||
|
fprintf (stderr, "SDL: couldn't initialize TTF: %s\n",
|
||||||
|
SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the font file with the requested point size */
|
||||||
|
font_big = TTF_OpenFont (QUOTE(FONTFILE), 16);
|
||||||
|
font_small = TTF_OpenFont (QUOTE(FONTFILE), 9);
|
||||||
|
if (! font_big || ! font_small) {
|
||||||
|
fprintf(stderr, "SDL: couldn't load font %s: %s\n",
|
||||||
|
QUOTE(FONTFILE), TTF_GetError());
|
||||||
|
besm6_close_panel();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
atexit (besm6_close_panel);
|
||||||
|
|
||||||
|
/* Drawing the static part of the BESM-6 panel */
|
||||||
|
draw_modifiers_static (0, 24, 10);
|
||||||
|
draw_modifiers_static (1, 400, 10);
|
||||||
|
draw_grp_static (180);
|
||||||
|
draw_brz_static (230);
|
||||||
|
|
||||||
|
/* Tell SDL to update the whole screen */
|
||||||
|
SDL_UpdateRect (screen, 0, 0, WIDTH, HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*sim_vm_init)() = init_panel;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Refreshing the window
|
||||||
|
*/
|
||||||
|
void besm6_draw_panel ()
|
||||||
|
{
|
||||||
|
if (! screen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Do the blinkenlights */
|
||||||
|
draw_modifiers_periodic (0, 24, 10);
|
||||||
|
draw_modifiers_periodic (1, 400, 10);
|
||||||
|
draw_grp_periodic (180);
|
||||||
|
draw_brz_periodic (230);
|
||||||
|
|
||||||
|
/* Tell SDL to update the whole screen */
|
||||||
|
SDL_UpdateRect (screen, 0, 0, WIDTH, HEIGHT);
|
||||||
|
|
||||||
|
/* Exit SIMH when window closed.*/
|
||||||
|
SDL_Event event;
|
||||||
|
if (SDL_PollEvent (&event) && event.type == SDL_QUIT)
|
||||||
|
longjmp (cpu_halt, SCPE_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_MAJOR_VERSION */
|
||||||
|
|
||||||
|
#else /* HAVE_LIBSDL */
|
||||||
|
void besm6_draw_panel (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBSDL */
|
319
BESM6/besm6_printer.c
Normal file
319
BESM6/besm6_printer.c
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
/*
|
||||||
|
* besm6_printer.c: BESM-6 line printer device
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
|
||||||
|
t_stat printer_event (UNIT *u);
|
||||||
|
void offset_gost_write (int num, FILE *fout);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Printer data structures
|
||||||
|
*
|
||||||
|
* printer_dev PRINTER device descriptor
|
||||||
|
* printer_unit PRINTER unit descriptor
|
||||||
|
* printer_reg PRINTER register list
|
||||||
|
*/
|
||||||
|
UNIT printer_unit [] = {
|
||||||
|
{ UDATA (printer_event, UNIT_ATTABLE+UNIT_SEQ, 0) },
|
||||||
|
{ UDATA (printer_event, UNIT_ATTABLE+UNIT_SEQ, 0) },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_STRIKES 10
|
||||||
|
struct acpu_t {
|
||||||
|
int curchar, feed, rampup;
|
||||||
|
int strikes;
|
||||||
|
int length;
|
||||||
|
unsigned char line[128][MAX_STRIKES];
|
||||||
|
} acpu[2];
|
||||||
|
|
||||||
|
#define PRN1_NOT_READY (1<<19)
|
||||||
|
#define PRN2_NOT_READY (1<<18)
|
||||||
|
|
||||||
|
/* 1 = можно пользоваться молоточками, 0 - бумага в процессе протяжки */
|
||||||
|
#define PRN1_LINEFEED (1<<23)
|
||||||
|
#define PRN2_LINEFEED (1<<22)
|
||||||
|
|
||||||
|
#define SLOW_START 100*MSEC
|
||||||
|
#define FAST_START 1*MSEC
|
||||||
|
#define LINEFEED_SYNC 1 /* Чтобы быстрее печатало; в жизни 20-25 мс/1.4 мс ~= 17 */
|
||||||
|
|
||||||
|
REG printer_reg[] = {
|
||||||
|
{ "Готов", &READY, 2, 2, 18, 1 },
|
||||||
|
{ "Прогон", &READY, 2, 2, 22, 1 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
MTAB printer_mod[] = {
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
t_stat printer_reset (DEVICE *dptr);
|
||||||
|
t_stat printer_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat printer_detach (UNIT *uptr);
|
||||||
|
|
||||||
|
DEVICE printer_dev = {
|
||||||
|
"PRN", printer_unit, printer_reg, printer_mod,
|
||||||
|
2, 8, 19, 1, 8, 50,
|
||||||
|
NULL, NULL, &printer_reset, NULL, &printer_attach, &printer_detach,
|
||||||
|
NULL, DEV_DISABLE | DEV_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset routine
|
||||||
|
*/
|
||||||
|
t_stat printer_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
memset(acpu, 0, sizeof (acpu));
|
||||||
|
acpu[0].rampup = acpu[1].rampup = SLOW_START;
|
||||||
|
sim_cancel (&printer_unit[0]);
|
||||||
|
sim_cancel (&printer_unit[1]);
|
||||||
|
READY |= PRN1_NOT_READY | PRN2_NOT_READY;
|
||||||
|
if (printer_unit[0].flags & UNIT_ATT)
|
||||||
|
READY &= ~PRN1_NOT_READY;
|
||||||
|
if (printer_unit[1].flags & UNIT_ATT)
|
||||||
|
READY &= ~PRN2_NOT_READY;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat printer_attach (UNIT *u, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat s;
|
||||||
|
int num = u - printer_unit;
|
||||||
|
|
||||||
|
if (u->flags & UNIT_ATT) {
|
||||||
|
/* Switching files cleanly */
|
||||||
|
detach_unit (u);
|
||||||
|
}
|
||||||
|
s = attach_unit (u, cptr);
|
||||||
|
if (s != SCPE_OK)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
READY &= ~(PRN1_NOT_READY >> num);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat printer_detach (UNIT *u)
|
||||||
|
{
|
||||||
|
int num = u - printer_unit;
|
||||||
|
READY |= PRN1_NOT_READY >> num;
|
||||||
|
return detach_unit (u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Управление двигателями, прогон
|
||||||
|
*/
|
||||||
|
void printer_control (int num, uint32 cmd)
|
||||||
|
{
|
||||||
|
UNIT *u = &printer_unit[num];
|
||||||
|
struct acpu_t * dev = acpu + num;
|
||||||
|
|
||||||
|
if (printer_dev.dctrl)
|
||||||
|
besm6_debug(">>> АЦПУ%d команда %o", num, cmd);
|
||||||
|
if (READY & (PRN1_NOT_READY >> num)) {
|
||||||
|
if (printer_dev.dctrl)
|
||||||
|
besm6_debug(">>> АЦПУ%d не готово", num, cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (cmd) {
|
||||||
|
case 1: /* linefeed */
|
||||||
|
READY &= ~(PRN1_LINEFEED >> num);
|
||||||
|
offset_gost_write (num, u->fileref);
|
||||||
|
dev->feed = LINEFEED_SYNC;
|
||||||
|
break;
|
||||||
|
case 4: /* start */
|
||||||
|
/* стартуем из состояния прогона для надежности */
|
||||||
|
dev->feed = LINEFEED_SYNC;
|
||||||
|
READY &= ~(PRN1_LINEFEED >> num);
|
||||||
|
if (dev->rampup)
|
||||||
|
sim_activate (u, dev->rampup);
|
||||||
|
dev->rampup = 0;
|
||||||
|
break;
|
||||||
|
case 10: /* motor and ribbon off */
|
||||||
|
case 8: /* motor off? (undocumented) */
|
||||||
|
case 2: /* ribbon off */
|
||||||
|
dev->rampup = cmd == 2 ? FAST_START : SLOW_START;
|
||||||
|
sim_cancel (u);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Управление молоточками
|
||||||
|
*/
|
||||||
|
void printer_hammer (int num, int pos, uint32 mask)
|
||||||
|
{
|
||||||
|
struct acpu_t * dev = acpu + num;
|
||||||
|
while (mask) {
|
||||||
|
if (mask & 1) {
|
||||||
|
int strike = 0;
|
||||||
|
while (dev->line[pos][strike] && strike < MAX_STRIKES)
|
||||||
|
++strike;
|
||||||
|
if (strike < MAX_STRIKES) {
|
||||||
|
dev->line[pos][strike] = dev->curchar;
|
||||||
|
if (pos + 1 > dev->length)
|
||||||
|
dev->length = pos + 1;
|
||||||
|
if (strike + 1 > dev->strikes)
|
||||||
|
dev->strikes = strike + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Событие: вращение барабана АЦПУ.
|
||||||
|
* Устанавливаем флаг прерывания.
|
||||||
|
*/
|
||||||
|
t_stat printer_event (UNIT *u)
|
||||||
|
{
|
||||||
|
int num = u - printer_unit;
|
||||||
|
struct acpu_t * dev = acpu + num;
|
||||||
|
|
||||||
|
if (dev->curchar < 0140) {
|
||||||
|
GRP |= GRP_PRN1_SYNC >> num;
|
||||||
|
++dev->curchar;
|
||||||
|
/* For next char */
|
||||||
|
sim_activate (u, 1400*USEC);
|
||||||
|
if (dev->feed && --dev->feed == 0) {
|
||||||
|
READY |= PRN1_LINEFEED >> num;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* For "zero" */
|
||||||
|
dev->curchar = 0;
|
||||||
|
GRP |= GRP_PRN1_ZERO >> num;
|
||||||
|
if (printer_dev.dctrl)
|
||||||
|
besm6_debug(">>> АЦПУ%d 'ноль'", num);
|
||||||
|
/* For first sync after "zero" */
|
||||||
|
sim_activate (u, 1000*USEC);
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gost_latin = 0; /* default cyrillics */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GOST-10859 encoding.
|
||||||
|
* Documentation: http://en.wikipedia.org/wiki/GOST_10859
|
||||||
|
*/
|
||||||
|
static const unsigned short gost_to_unicode_cyr [256] = {
|
||||||
|
/* 000-007 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||||
|
/* 010-017 */ 0x38, 0x39, 0x2b, 0x2d, 0x2f, 0x2c, 0x2e, 0x2423,
|
||||||
|
/* 020-027 */ 0x65, 0x2191, 0x28, 0x29, 0xd7, 0x3d, 0x3b, 0x5b,
|
||||||
|
/* 030-037 */ 0x5d, 0x2a, 0x2018, 0x2019, 0x2260, 0x3c, 0x3e, 0x3a,
|
||||||
|
/* 040-047 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||||
|
/* 050-057 */ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
|
||||||
|
/* 060-067 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||||
|
/* 070-077 */ 0x0428, 0x0429, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x44,
|
||||||
|
/* 100-107 */ 0x46, 0x47, 0x49, 0x4a, 0x4c, 0x4e, 0x51, 0x52,
|
||||||
|
/* 110-117 */ 0x53, 0x55, 0x56, 0x57, 0x5a, 0x203e, 0x2264, 0x2265,
|
||||||
|
/* 120-127 */ 0x2228, 0x2227, 0x2283, 0xac, 0xf7, 0x2261, 0x25, 0x25c7,
|
||||||
|
/* 130-137 */ 0x7c, 0x2015, 0x5f, 0x21, 0x22, 0x042a, 0xb0, 0x2032,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned short gost_to_unicode_lat [256] = {
|
||||||
|
/* 000-007 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||||
|
/* 010-017 */ 0x38, 0x39, 0x2b, 0x2d, 0x2f, 0x2c, 0x2e, 0x2423,
|
||||||
|
/* 020-027 */ 0x65, 0x2191, 0x28, 0x29, 0xd7, 0x3d, 0x3b, 0x5b,
|
||||||
|
/* 030-037 */ 0x5d, 0x2a, 0x2018, 0x2019, 0x2260, 0x3c, 0x3e, 0x3a,
|
||||||
|
/* 040-047 */ 0x41, 0x0411, 0x42, 0x0413, 0x0414, 0x45, 0x0416, 0x0417,
|
||||||
|
/* 050-057 */ 0x0418, 0x0419, 0x4b, 0x041b, 0x4d, 0x48, 0x4f, 0x041f,
|
||||||
|
/* 060-067 */ 0x50, 0x43, 0x54, 0x59, 0x0424, 0x58, 0x0426, 0x0427,
|
||||||
|
/* 070-077 */ 0x0428, 0x0429, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x44,
|
||||||
|
/* 100-107 */ 0x46, 0x47, 0x49, 0x4a, 0x4c, 0x4e, 0x51, 0x52,
|
||||||
|
/* 110-117 */ 0x53, 0x55, 0x56, 0x57, 0x5a, 0x203e, 0x2264, 0x2265,
|
||||||
|
/* 120-127 */ 0x2228, 0x2227, 0x2283, 0xac, 0xf7, 0x2261, 0x25, 0x25c7,
|
||||||
|
/* 130-137 */ 0x7c, 0x2015, 0x5f, 0x21, 0x22, 0x042a, 0xb0, 0x2032,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Write Unicode symbol to file.
|
||||||
|
* Convert to UTF-8 encoding:
|
||||||
|
* 00000000.0xxxxxxx -> 0xxxxxxx
|
||||||
|
* 00000xxx.xxyyyyyy -> 110xxxxx, 10yyyyyy
|
||||||
|
* xxxxyyyy.yyzzzzzz -> 1110xxxx, 10yyyyyy, 10zzzzzz
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
utf8_putc (unsigned short ch, FILE *fout)
|
||||||
|
{
|
||||||
|
if (ch < 0x80) {
|
||||||
|
putc (ch, fout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ch < 0x800) {
|
||||||
|
putc (ch >> 6 | 0xc0, fout);
|
||||||
|
putc ((ch & 0x3f) | 0x80, fout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
putc (ch >> 12 | 0xe0, fout);
|
||||||
|
putc (((ch >> 6) & 0x3f) | 0x80, fout);
|
||||||
|
putc ((ch & 0x3f) | 0x80, fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short
|
||||||
|
gost_to_unicode (unsigned char ch)
|
||||||
|
{
|
||||||
|
return gost_latin ? gost_to_unicode_lat [ch] :
|
||||||
|
gost_to_unicode_cyr [ch];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write GOST-10859 symbol to file.
|
||||||
|
* Convert to local encoding (UTF-8, KOI8-R, CP-1251, CP-866).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gost_putc (unsigned char ch, FILE *fout)
|
||||||
|
{
|
||||||
|
unsigned short u;
|
||||||
|
|
||||||
|
u = gost_to_unicode (ch);
|
||||||
|
if (! u)
|
||||||
|
u = ' ';
|
||||||
|
utf8_putc (u, fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write GOST-10859 string with overprint to file in UTF-8.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
offset_gost_write (int num, FILE *fout)
|
||||||
|
{
|
||||||
|
struct acpu_t * dev = acpu + num;
|
||||||
|
int s, p;
|
||||||
|
for (s = 0; s < dev->strikes; ++s) {
|
||||||
|
if (s)
|
||||||
|
fputc ('\r', fout);
|
||||||
|
for (p = 0; p < dev->length; ++p) {
|
||||||
|
gost_putc (dev->line[p][s] - 1, fout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fputc ('\n', fout);
|
||||||
|
memset(dev->line, 0, sizeof (dev->line));
|
||||||
|
dev->length = dev->strikes = 0;
|
||||||
|
}
|
447
BESM6/besm6_punch.c
Normal file
447
BESM6/besm6_punch.c
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
/*
|
||||||
|
* besm6_punch.c: BESM-6 punchcard/punchtape devices
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*/
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
|
||||||
|
t_stat fs_event (UNIT *u);
|
||||||
|
t_stat uvvk_event (UNIT *u);
|
||||||
|
|
||||||
|
UNIT fs_unit [] = {
|
||||||
|
{ UDATA (fs_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||||
|
{ UDATA (fs_event, UNIT_SEQ+UNIT_ATTABLE, 0) },
|
||||||
|
};
|
||||||
|
|
||||||
|
int curchar[2], feed[2], isfifo[2];
|
||||||
|
char line[2][128];
|
||||||
|
|
||||||
|
#define FS1_READY (1<<15)
|
||||||
|
#define FS2_READY (1<<14)
|
||||||
|
|
||||||
|
/* #define NEGATIVE_RDY */
|
||||||
|
|
||||||
|
#ifndef NEGATIVE_RDY
|
||||||
|
#define ENB_RDY SET_RDY
|
||||||
|
#define DIS_RDY CLR_RDY
|
||||||
|
#define IS_RDY ISSET_RDY
|
||||||
|
#else
|
||||||
|
#define ENB_RDY CLR_RDY
|
||||||
|
#define DIS_RDY SET_RDY
|
||||||
|
#define IS_RDY ISCLR_RDY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SET_RDY(x) do READY |= x; while (0)
|
||||||
|
#define CLR_RDY(x) do READY &= ~(x); while (0)
|
||||||
|
#define ISSET_RDY(x) ((READY & (x)) != 0)
|
||||||
|
#define ISCLR_RDY(x) ((READY & (x)) == 0)
|
||||||
|
|
||||||
|
#define FS_RATE 1000*MSEC/1500
|
||||||
|
|
||||||
|
unsigned char FS[2];
|
||||||
|
|
||||||
|
REG fs_reg[] = {
|
||||||
|
{ "Готов", &READY, 2, 2, 14, 1 },
|
||||||
|
{ "ФС1500-1", &FS[0], 8, 8, 0, 1 },
|
||||||
|
{ "ФС1500-2", &FS[2], 8, 8, 0, 1 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
MTAB fs_mod[] = {
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
t_stat fs_reset (DEVICE *dptr);
|
||||||
|
t_stat fs_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat fs_detach (UNIT *uptr);
|
||||||
|
|
||||||
|
DEVICE fs_dev = {
|
||||||
|
"FS", fs_unit, fs_reg, fs_mod,
|
||||||
|
2, 8, 19, 1, 8, 50,
|
||||||
|
NULL, NULL, &fs_reset, NULL, &fs_attach, &fs_detach,
|
||||||
|
NULL, DEV_DISABLE | DEV_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CARD_LEN 120
|
||||||
|
enum {
|
||||||
|
FS_IDLE,
|
||||||
|
FS_STARTING,
|
||||||
|
FS_RUNNING,
|
||||||
|
FS_IMAGE,
|
||||||
|
FS_IMAGE_LAST = FS_IMAGE + CARD_LEN - 1,
|
||||||
|
FS_TOOLONG,
|
||||||
|
FS_FILLUP,
|
||||||
|
FS_FILLUP_LAST = FS_FILLUP + CARD_LEN - 1,
|
||||||
|
FS_ENDA3,
|
||||||
|
FS_ENDA3_LAST = FS_ENDA3 + CARD_LEN - 1,
|
||||||
|
FS_TAIL,
|
||||||
|
} fs_state[2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset routine
|
||||||
|
*/
|
||||||
|
t_stat fs_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
sim_cancel (&fs_unit[0]);
|
||||||
|
sim_cancel (&fs_unit[1]);
|
||||||
|
fs_state[0] = fs_state[1] = FS_IDLE;
|
||||||
|
DIS_RDY(FS1_READY | FS2_READY);
|
||||||
|
if (fs_unit[0].flags & UNIT_ATT)
|
||||||
|
ENB_RDY(FS1_READY);
|
||||||
|
if (fs_unit[1].flags & UNIT_ATT)
|
||||||
|
ENB_RDY(FS2_READY);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat fs_attach (UNIT *u, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat s;
|
||||||
|
int num = u - fs_unit;
|
||||||
|
s = attach_unit (u, cptr);
|
||||||
|
if (s != SCPE_OK)
|
||||||
|
return s;
|
||||||
|
isfifo[num] = (0 == sim_set_fifo_nonblock (u->fileref));
|
||||||
|
ENB_RDY(FS1_READY >> num);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat fs_detach (UNIT *u)
|
||||||
|
{
|
||||||
|
int num = u - fs_unit;
|
||||||
|
DIS_RDY(FS1_READY >> num);
|
||||||
|
return detach_unit (u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Управление двигателем, лампой, протяжкой
|
||||||
|
*/
|
||||||
|
void fs_control (int num, uint32 cmd)
|
||||||
|
{
|
||||||
|
UNIT *u = &fs_unit[num];
|
||||||
|
|
||||||
|
static int bytecnt = 0;
|
||||||
|
if (fs_dev.dctrl)
|
||||||
|
besm6_debug("<<< ФС1500-%d команда %o", num, cmd);
|
||||||
|
if (! IS_RDY(FS1_READY >> num)) {
|
||||||
|
if (fs_dev.dctrl)
|
||||||
|
besm6_debug("<<< ФС1500-%d не готово", num, cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (cmd) {
|
||||||
|
case 0: /* полное выключение */
|
||||||
|
sim_cancel (u);
|
||||||
|
fs_state[num] = FS_IDLE;
|
||||||
|
if (fs_dev.dctrl)
|
||||||
|
besm6_debug("<<<ФС1500-%d ВЫКЛ..", num);
|
||||||
|
bytecnt = 0;
|
||||||
|
break;
|
||||||
|
case 4: /* двигатель без протяжки */
|
||||||
|
fs_state[num] = FS_STARTING;
|
||||||
|
if (fs_dev.dctrl)
|
||||||
|
besm6_debug("<<<ФС1500-%d ВКЛ.", num);
|
||||||
|
sim_cancel (u);
|
||||||
|
break;
|
||||||
|
case 5: /* протяжка */
|
||||||
|
if (fs_state[num] == FS_IDLE)
|
||||||
|
besm6_debug("<<< ФС1500-%d протяжка без мотора", num);
|
||||||
|
else if (fs_state[num] != FS_TAIL) {
|
||||||
|
sim_activate (u, FS_RATE);
|
||||||
|
bytecnt++;
|
||||||
|
} else {
|
||||||
|
if (! isfifo[num]) {
|
||||||
|
fs_detach(u);
|
||||||
|
fs_state[num] = FS_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
besm6_debug ("<<< ФС1500-%d неизвестная команда %o", num, cmd);
|
||||||
|
}
|
||||||
|
if (cmd && fs_dev.dctrl) {
|
||||||
|
besm6_debug("<<<ФС1500-%d: %d симв.", num, bytecnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char unicode_to_gost (unsigned short val);
|
||||||
|
static int utf8_getc (FILE *fin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Событие: читаем очередной символ с перфоленты в регистр.
|
||||||
|
* Устанавливаем флаг прерывания.
|
||||||
|
*/
|
||||||
|
t_stat fs_event (UNIT *u)
|
||||||
|
{
|
||||||
|
int num = u - fs_unit;
|
||||||
|
again:
|
||||||
|
if (fs_state[num] == FS_STARTING) {
|
||||||
|
/* По первому прерыванию после запуска двигателя ничего не читаем */
|
||||||
|
FS[num] = 0;
|
||||||
|
fs_state[num] = FS_RUNNING;
|
||||||
|
} else if (fs_state[num] == FS_RUNNING) {
|
||||||
|
int ch;
|
||||||
|
/* переводы строк игнорируются */
|
||||||
|
while ((ch = utf8_getc (u->fileref)) == '\n');
|
||||||
|
if (ch < 0) {
|
||||||
|
/* хвост ленты без пробивок */
|
||||||
|
FS[num] = 0;
|
||||||
|
fs_state[num] = FS_TAIL;
|
||||||
|
} else if (ch == '\f') {
|
||||||
|
fs_state[num] = FS_IMAGE;
|
||||||
|
goto again;
|
||||||
|
} else {
|
||||||
|
ch = FS[num] = unicode_to_gost (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) {
|
||||||
|
int ch = utf8_getc (u->fileref);
|
||||||
|
if (ch < 0) {
|
||||||
|
/* обрыв ленты */
|
||||||
|
FS[num] = 0;
|
||||||
|
fs_state[num] = FS_TAIL;
|
||||||
|
} else if (ch == '\n') {
|
||||||
|
/* идем дополнять образ карты нулевыми байтами */
|
||||||
|
fs_state[num] = FS_FILLUP + (fs_state[num] - FS_IMAGE);
|
||||||
|
goto again;
|
||||||
|
} else if (ch == '\f') {
|
||||||
|
if (fs_state[num] != FS_IMAGE)
|
||||||
|
besm6_debug("<<< ENDA3 requested mid-card?");
|
||||||
|
fs_state[num] = FS_ENDA3;
|
||||||
|
goto again;
|
||||||
|
} else {
|
||||||
|
ch = FS[num] = unicode_to_gost (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;
|
||||||
|
++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) {
|
||||||
|
FS[num] = 0;
|
||||||
|
if (++fs_state[num] == FS_ENDA3) {
|
||||||
|
fs_state[num] = FS_IMAGE;
|
||||||
|
}
|
||||||
|
} else if (FS_ENDA3 <= fs_state[num] && fs_state[num] <= FS_ENDA3_LAST) {
|
||||||
|
if ((fs_state[num] - FS_ENDA3) % 5 == 0)
|
||||||
|
FS[num] = 0200;
|
||||||
|
else
|
||||||
|
FS[num] = 0;
|
||||||
|
if (++fs_state[num] == FS_TAIL) {
|
||||||
|
fs_state[num] = FS_RUNNING;
|
||||||
|
}
|
||||||
|
} else if (fs_state[num] == FS_IDLE || fs_state[num] == FS_TAIL) {
|
||||||
|
FS[num] = 0;
|
||||||
|
}
|
||||||
|
GRP |= GRP_FS1_SYNC >> num;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_read(int num) {
|
||||||
|
if (fs_dev.dctrl)
|
||||||
|
besm6_debug("<<< ФС1500-%d: байт %03o", num, FS[num]);
|
||||||
|
|
||||||
|
return FS[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char
|
||||||
|
unicode_to_gost (unsigned short val)
|
||||||
|
{
|
||||||
|
static const unsigned char tab0 [256] = {
|
||||||
|
/* 00 - 07 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* 08 - 0f */ 017, 017, 0214, 017, 017, 0174, 017, 017,
|
||||||
|
/* 10 - 17 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* 18 - 1f */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* !"#$%&' */ 0017, 0133, 0134, 0034, 0127, 0126, 0121, 0033,
|
||||||
|
/* ()*+,-./ */ 0022, 0023, 0031, 0012, 0015, 0013, 0016, 0014,
|
||||||
|
/* 01234567 */ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
|
||||||
|
/* 89:;<=>? */ 0010, 0011, 0037, 0026, 0035, 0025, 0036, 0136,
|
||||||
|
/* @ABCDEFG */ 0021, 0040, 0042, 0061, 0077, 0045, 0100, 0101,
|
||||||
|
/* HIJKLMNO */ 0055, 0102, 0103, 0052, 0104, 0054, 0105, 0056,
|
||||||
|
/* PQRSTUVW */ 0060, 0106, 0107, 0110, 0062, 0111, 0112, 0113,
|
||||||
|
/* XYZ[\]^_ */ 0065, 0063, 0114, 0027, 017, 0030, 0115, 0132,
|
||||||
|
/* `abcdefg */ 0032, 0040, 0042, 0061, 0077, 0045, 0100, 0101,
|
||||||
|
/* hijklmno */ 0055, 0102, 0103, 0052, 0104, 0054, 0105, 0056,
|
||||||
|
/* pqrstuvw */ 0060, 0106, 0107, 0110, 0062, 0111, 0112, 0113,
|
||||||
|
/* xyz{|}~ */ 0065, 0063, 0114, 017, 0130, 017, 0123, 017,
|
||||||
|
/* 80 - 87 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* 88 - 8f */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* 90 - 97 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* 98 - 9f */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* a0 - a7 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* a8 - af */ 017, 017, 017, 017, 0123, 017, 017, 017,
|
||||||
|
/* b0 - b7 */ 0136, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* b8 - bf */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* c0 - c7 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* c8 - cf */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* d0 - d7 */ 017, 017, 017, 017, 017, 017, 017, 0024,
|
||||||
|
/* d8 - df */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* e0 - e7 */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* e8 - ef */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
/* f0 - f7 */ 017, 017, 017, 017, 017, 017, 017, 0124,
|
||||||
|
/* f8 - ff */ 017, 017, 017, 017, 017, 017, 017, 017,
|
||||||
|
};
|
||||||
|
switch (val >> 8) {
|
||||||
|
case 0x00:
|
||||||
|
return tab0 [val];
|
||||||
|
case 0x04:
|
||||||
|
switch ((unsigned char) val) {
|
||||||
|
case 0x10: return 0040;
|
||||||
|
case 0x11: return 0041;
|
||||||
|
case 0x12: return 0042;
|
||||||
|
case 0x13: return 0043;
|
||||||
|
case 0x14: return 0044;
|
||||||
|
case 0x15: return 0045;
|
||||||
|
case 0x16: return 0046;
|
||||||
|
case 0x17: return 0047;
|
||||||
|
case 0x18: return 0050;
|
||||||
|
case 0x19: return 0051;
|
||||||
|
case 0x1a: return 0052;
|
||||||
|
case 0x1b: return 0053;
|
||||||
|
case 0x1c: return 0054;
|
||||||
|
case 0x1d: return 0055;
|
||||||
|
case 0x1e: return 0056;
|
||||||
|
case 0x1f: return 0057;
|
||||||
|
case 0x20: return 0060;
|
||||||
|
case 0x21: return 0061;
|
||||||
|
case 0x22: return 0062;
|
||||||
|
case 0x23: return 0063;
|
||||||
|
case 0x24: return 0064;
|
||||||
|
case 0x25: return 0065;
|
||||||
|
case 0x26: return 0066;
|
||||||
|
case 0x27: return 0067;
|
||||||
|
case 0x28: return 0070;
|
||||||
|
case 0x29: return 0071;
|
||||||
|
case 0x2a: return 0135;
|
||||||
|
case 0x2b: return 0072;
|
||||||
|
case 0x2c: return 0073;
|
||||||
|
case 0x2d: return 0074;
|
||||||
|
case 0x2e: return 0075;
|
||||||
|
case 0x2f: return 0076;
|
||||||
|
case 0x30: return 0040;
|
||||||
|
case 0x31: return 0041;
|
||||||
|
case 0x32: return 0042;
|
||||||
|
case 0x33: return 0043;
|
||||||
|
case 0x34: return 0044;
|
||||||
|
case 0x35: return 0045;
|
||||||
|
case 0x36: return 0046;
|
||||||
|
case 0x37: return 0047;
|
||||||
|
case 0x38: return 0050;
|
||||||
|
case 0x39: return 0051;
|
||||||
|
case 0x3a: return 0052;
|
||||||
|
case 0x3b: return 0053;
|
||||||
|
case 0x3c: return 0054;
|
||||||
|
case 0x3d: return 0055;
|
||||||
|
case 0x3e: return 0056;
|
||||||
|
case 0x3f: return 0057;
|
||||||
|
case 0x40: return 0060;
|
||||||
|
case 0x41: return 0061;
|
||||||
|
case 0x42: return 0062;
|
||||||
|
case 0x43: return 0063;
|
||||||
|
case 0x44: return 0064;
|
||||||
|
case 0x45: return 0065;
|
||||||
|
case 0x46: return 0066;
|
||||||
|
case 0x47: return 0067;
|
||||||
|
case 0x48: return 0070;
|
||||||
|
case 0x49: return 0071;
|
||||||
|
case 0x4a: return 0135;
|
||||||
|
case 0x4b: return 0072;
|
||||||
|
case 0x4c: return 0073;
|
||||||
|
case 0x4d: return 0074;
|
||||||
|
case 0x4e: return 0075;
|
||||||
|
case 0x4f: return 0076;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
switch ((unsigned char) val) {
|
||||||
|
case 0x15: return 0131;
|
||||||
|
case 0x18: return 0032;
|
||||||
|
case 0x19: return 0033;
|
||||||
|
case 0x32: return 0137;
|
||||||
|
case 0x3e: return 0115;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x21:
|
||||||
|
switch ((unsigned char) val) {
|
||||||
|
case 0x2f: return 0020;
|
||||||
|
case 0x91: return 0021;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x22:
|
||||||
|
switch ((unsigned char) val) {
|
||||||
|
case 0x27: return 0121;
|
||||||
|
case 0x28: return 0120;
|
||||||
|
case 0x60: return 0034;
|
||||||
|
case 0x61: return 0125;
|
||||||
|
case 0x64: return 0116;
|
||||||
|
case 0x65: return 0117;
|
||||||
|
case 0x83: return 0122;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x25:
|
||||||
|
switch ((unsigned char) val) {
|
||||||
|
case 0xc7: return 0127;
|
||||||
|
case 0xca: return 0127;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 017;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read Unicode symbol from file.
|
||||||
|
* Convert from UTF-8 encoding.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
utf8_getc (FILE *fin)
|
||||||
|
{
|
||||||
|
int c1, c2, c3;
|
||||||
|
again:
|
||||||
|
c1 = getc (fin);
|
||||||
|
if (c1 < 0 || ! (c1 & 0x80))
|
||||||
|
return c1;
|
||||||
|
c2 = getc (fin);
|
||||||
|
if (! (c1 & 0x20))
|
||||||
|
return (c1 & 0x1f) << 6 | (c2 & 0x3f);
|
||||||
|
c3 = getc (fin);
|
||||||
|
if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) {
|
||||||
|
/* Skip zero width no-break space. */
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
return (c1 & 0x0f) << 12 | (c2 & 0x3f) << 6 | (c3 & 0x3f);
|
||||||
|
}
|
733
BESM6/besm6_sys.c
Normal file
733
BESM6/besm6_sys.c
Normal file
|
@ -0,0 +1,733 @@
|
||||||
|
/*
|
||||||
|
* besm6_sys.c: BESM-6 simulator interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, Serge Vakulenko
|
||||||
|
* Copyright (c) 2009, Leonid Broukhis
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
* OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
* Except as contained in this notice, the name of Leonid Broukhis or
|
||||||
|
* Serge Vakulenko shall not be used in advertising or otherwise to promote
|
||||||
|
* the sale, use or other dealings in this Software without prior written
|
||||||
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
|
*
|
||||||
|
* This file implements three essential functions:
|
||||||
|
*
|
||||||
|
* sim_load() - loading and dumping memory and CPU state
|
||||||
|
* in a way, specific for BESM-6 architecture
|
||||||
|
* fprint_sym() - print a machune instruction using
|
||||||
|
* opcode mnemonic or in a digital format
|
||||||
|
* parse_sym() - scan a string and build an instruction
|
||||||
|
* word from it
|
||||||
|
*/
|
||||||
|
#include "besm6_defs.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
const char *opname_short_bemsh [64] = {
|
||||||
|
"зп", "зпм", "рег", "счм", "сл", "вч", "вчоб","вчаб",
|
||||||
|
"сч", "и", "нтж", "слц", "знак","или", "дел", "умн",
|
||||||
|
"сбр", "рзб", "чед", "нед", "слп", "вчп", "сд", "рж",
|
||||||
|
"счрж","счмр","э32", "увв", "слпа","вчпа","сда", "ржа",
|
||||||
|
"уи", "уим", "счи", "счим","уии", "сли", "э46", "э47",
|
||||||
|
"э50", "э51", "э52", "э53", "э54", "э55", "э56", "э57",
|
||||||
|
"э60", "э61", "э62", "э63", "э64", "э65", "э66", "э67",
|
||||||
|
"э70", "э71", "э72", "э73", "э74", "э75", "э76", "э77",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *opname_long_bemsh [16] = {
|
||||||
|
"э20", "э21", "мода","мод", "уиа", "слиа","по", "пе",
|
||||||
|
"пб", "пв", "выпр","стоп","пио", "пино","э36", "цикл",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *opname_short_madlen [64] = {
|
||||||
|
"atx", "stx", "mod", "xts", "a+x", "a-x", "x-a", "amx",
|
||||||
|
"xta", "aax", "aex", "arx", "avx", "aox", "a/x", "a*x",
|
||||||
|
"apx", "aux", "acx", "anx", "e+x", "e-x", "asx", "xtr",
|
||||||
|
"rte", "yta", "*32", "ext", "e+n", "e-n", "asn", "ntr",
|
||||||
|
"ati", "sti", "ita", "its", "mtj", "j+m", "*46", "*47",
|
||||||
|
"*50", "*51", "*52", "*53", "*54", "*55", "*56", "*57",
|
||||||
|
"*60", "*61", "*62", "*63", "*64", "*65", "*66", "*67",
|
||||||
|
"*70", "*71", "*72", "*73", "*74", "*75", "*76", "*77",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *opname_long_madlen [16] = {
|
||||||
|
"*20", "*21", "utc", "wtc", "vtm", "utm", "uza", "u1a",
|
||||||
|
"uj", "vjm", "ij", "stop", "vzm", "v1m", "*36", "vlm",
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выдача мнемоники по коду инструкции.
|
||||||
|
* Код должен быть в диапазоне 000..077 или 0200..0370.
|
||||||
|
*/
|
||||||
|
const char *besm6_opname (int opcode)
|
||||||
|
{
|
||||||
|
if (sim_switches & SWMASK ('L')) {
|
||||||
|
/* Latin mnemonics. */
|
||||||
|
if (opcode & 0200)
|
||||||
|
return opname_long_madlen [(opcode >> 3) & 017];
|
||||||
|
return opname_short_madlen [opcode];
|
||||||
|
}
|
||||||
|
if (opcode & 0200)
|
||||||
|
return opname_long_bemsh [(opcode >> 3) & 017];
|
||||||
|
return opname_short_bemsh [opcode];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выдача кода инструкции по мнемонике (UTF-8).
|
||||||
|
*/
|
||||||
|
int besm6_opcode (char *instr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<64; ++i)
|
||||||
|
if (strcmp (opname_short_bemsh[i], instr) == 0 ||
|
||||||
|
strcmp (opname_short_madlen[i], instr) == 0)
|
||||||
|
return i;
|
||||||
|
for (i=0; i<16; ++i)
|
||||||
|
if (strcmp (opname_long_bemsh[i], instr) == 0 ||
|
||||||
|
strcmp (opname_long_madlen[i], instr) == 0)
|
||||||
|
return (i << 3) | 0200;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выдача на консоль и в файл протокола.
|
||||||
|
* Если первый символ формата - подчерк, на консоль не печатаем.
|
||||||
|
* Добавляет перевод строки.
|
||||||
|
*/
|
||||||
|
void besm6_log (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (*fmt == '_')
|
||||||
|
++fmt;
|
||||||
|
else {
|
||||||
|
va_start (args, fmt);
|
||||||
|
vprintf (fmt, args);
|
||||||
|
printf ("\r\n");
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
if (sim_log) {
|
||||||
|
va_start (args, fmt);
|
||||||
|
vfprintf (sim_log, fmt, args);
|
||||||
|
if (sim_log == stdout)
|
||||||
|
fprintf (sim_log, "\r");
|
||||||
|
fprintf (sim_log, "\n");
|
||||||
|
fflush (sim_log);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Не добавляет перевод строки.
|
||||||
|
*/
|
||||||
|
void besm6_log_cont (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (*fmt == '_')
|
||||||
|
++fmt;
|
||||||
|
else {
|
||||||
|
va_start (args, fmt);
|
||||||
|
vprintf (fmt, args);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
if (sim_log) {
|
||||||
|
va_start (args, fmt);
|
||||||
|
vfprintf (sim_log, fmt, args);
|
||||||
|
fflush (sim_log);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Выдача на консоль и в файл отладки: если включён режим "cpu debug".
|
||||||
|
* Добавляет перевод строки.
|
||||||
|
*/
|
||||||
|
void besm6_debug (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, fmt);
|
||||||
|
vprintf (fmt, args);
|
||||||
|
printf ("\r\n");
|
||||||
|
va_end (args);
|
||||||
|
if (sim_deb && sim_deb != stdout) {
|
||||||
|
va_start (args, fmt);
|
||||||
|
vfprintf (sim_deb, fmt, args);
|
||||||
|
fprintf (sim_deb, "\n");
|
||||||
|
fflush (sim_deb);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Преобразование вещественного числа в формат БЭСМ-6.
|
||||||
|
*
|
||||||
|
* Представление чисел в IEEE 754 (double):
|
||||||
|
* 64 63———53 52————–1
|
||||||
|
* знак порядок мантисса
|
||||||
|
* Старший (53-й) бит мантиссы не хранится и всегда равен 1.
|
||||||
|
*
|
||||||
|
* Представление чисел в БЭСМ-6:
|
||||||
|
* 48——–42 41 40————————————————–1
|
||||||
|
* порядок знак мантисса в доп. коде
|
||||||
|
*/
|
||||||
|
t_value ieee_to_besm6 (double d)
|
||||||
|
{
|
||||||
|
t_value word;
|
||||||
|
int exponent;
|
||||||
|
int sign;
|
||||||
|
|
||||||
|
sign = d < 0;
|
||||||
|
if (sign)
|
||||||
|
d = -d;
|
||||||
|
d = frexp (d, &exponent);
|
||||||
|
/* 0.5 <= d < 1.0 */
|
||||||
|
d = ldexp (d, 40);
|
||||||
|
word = (t_value)d;
|
||||||
|
if (d - word >= 0.5)
|
||||||
|
word += 1; /* Округление. */
|
||||||
|
if (exponent < -64)
|
||||||
|
return 0LL; /* Близкое к нулю число */
|
||||||
|
if (exponent > 63) {
|
||||||
|
return sign ?
|
||||||
|
0xFEFFFFFFFFFFLL : /* Максимальное число */
|
||||||
|
0xFF0000000000LL; /* Минимальное число */
|
||||||
|
}
|
||||||
|
if (sign)
|
||||||
|
word = 0x20000000000LL-word; /* Знак. */
|
||||||
|
word |= ((t_value) (exponent + 64)) << 41;
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
|
||||||
|
double besm6_to_ieee (t_value word)
|
||||||
|
{
|
||||||
|
double mantissa;
|
||||||
|
int exponent;
|
||||||
|
|
||||||
|
/* Убираем свертку */
|
||||||
|
word &= BITS48;
|
||||||
|
|
||||||
|
/* Сдвигаем так, чтобы знак мантиссы пришелся на знак целого;
|
||||||
|
* таким образом, mantissa равно исходной мантиссе, умноженной на 2**63.
|
||||||
|
*/
|
||||||
|
mantissa = (double)(((t_int64) word) << (64 - 48 + 7));
|
||||||
|
|
||||||
|
exponent = word >> 41;
|
||||||
|
|
||||||
|
/* Порядок смещен вверх на 64, и мантиссу нужно скорректировать */
|
||||||
|
return ldexp (mantissa, exponent - 64 - 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Пропуск пробелов.
|
||||||
|
*/
|
||||||
|
char *skip_spaces (char *p)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
if (*p == (char) 0xEF && p[1] == (char) 0xBB && p[2] == (char) 0xBF) {
|
||||||
|
/* Skip zero width no-break space. */
|
||||||
|
p += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*p == ' ' || *p == '\t' || *p == '\r') {
|
||||||
|
++p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch Unicode symbol from UTF-8 string.
|
||||||
|
* Advance string pointer.
|
||||||
|
*/
|
||||||
|
int utf8_to_unicode (char **p)
|
||||||
|
{
|
||||||
|
int c1, c2, c3;
|
||||||
|
|
||||||
|
c1 = (unsigned char) *(*p)++;
|
||||||
|
if (! (c1 & 0x80))
|
||||||
|
return c1;
|
||||||
|
c2 = (unsigned char) *(*p)++;
|
||||||
|
if (! (c1 & 0x20))
|
||||||
|
return (c1 & 0x1f) << 6 | (c2 & 0x3f);
|
||||||
|
c3 = (unsigned char) *(*p)++;
|
||||||
|
return (c1 & 0x0f) << 12 | (c2 & 0x3f) << 6 | (c3 & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *besm6_parse_octal (char *cptr, int *offset)
|
||||||
|
{
|
||||||
|
char *eptr;
|
||||||
|
|
||||||
|
*offset = strtol (cptr, &eptr, 8);
|
||||||
|
if (eptr == cptr)
|
||||||
|
return 0;
|
||||||
|
return eptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *get_alnum (char *iptr, char *optr)
|
||||||
|
{
|
||||||
|
while ((*iptr >= 'a' && *iptr<='z') ||
|
||||||
|
(*iptr >= 'A' && *iptr<='Z') ||
|
||||||
|
(*iptr >= '0' && *iptr<='9') || (*iptr & 0x80)) {
|
||||||
|
*optr++ = *iptr++;
|
||||||
|
}
|
||||||
|
*optr = 0;
|
||||||
|
return iptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse single instruction (half word).
|
||||||
|
* Allow mnemonics or octal code.
|
||||||
|
*/
|
||||||
|
char *parse_instruction (char *cptr, uint32 *val)
|
||||||
|
{
|
||||||
|
int opcode, reg, addr, negate;
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
cptr = skip_spaces (cptr); /* absorb spaces */
|
||||||
|
if (*cptr >= '0' && *cptr <= '7') {
|
||||||
|
/* Восьмеричное представление. */
|
||||||
|
cptr = besm6_parse_octal (cptr, ®); /* get register */
|
||||||
|
if (! cptr || reg > 15) {
|
||||||
|
/*printf ("Bad register\n");*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cptr = skip_spaces (cptr); /* absorb spaces */
|
||||||
|
if (*cptr == '2' || *cptr == '3') {
|
||||||
|
/* Длинная команда. */
|
||||||
|
cptr = besm6_parse_octal (cptr, &opcode);
|
||||||
|
if (! cptr || opcode < 020 || opcode > 037) {
|
||||||
|
/*printf ("Bad long opcode\n");*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
opcode <<= 3;
|
||||||
|
} else {
|
||||||
|
/* Короткая команда. */
|
||||||
|
cptr = besm6_parse_octal (cptr, &opcode);
|
||||||
|
if (! cptr || opcode > 0177) {
|
||||||
|
/*printf ("Bad short opcode\n");*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cptr = besm6_parse_octal (cptr, &addr); /* get address */
|
||||||
|
if (! cptr || addr > BITS(15) ||
|
||||||
|
(opcode <= 0177 && addr > BITS(12))) {
|
||||||
|
/*printf ("Bad address\n");*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Мнемоническое представление команды. */
|
||||||
|
cptr = get_alnum (cptr, gbuf); /* get opcode */
|
||||||
|
opcode = besm6_opcode (gbuf);
|
||||||
|
if (opcode < 0) {
|
||||||
|
/*printf ("Bad opname: %s\n", gbuf);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
negate = 0;
|
||||||
|
cptr = skip_spaces (cptr); /* absorb spaces */
|
||||||
|
if (*cptr == '-') { /* negative offset */
|
||||||
|
negate = 1;
|
||||||
|
cptr = skip_spaces (cptr + 1); /* absorb spaces */
|
||||||
|
}
|
||||||
|
addr = 0;
|
||||||
|
if (*cptr >= '0' && *cptr <= '7') {
|
||||||
|
/* Восьмеричный адрес. */
|
||||||
|
cptr = besm6_parse_octal (cptr, &addr);
|
||||||
|
if (! cptr || addr > BITS(15)) {
|
||||||
|
/*printf ("Bad address: %o\n", addr);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (negate)
|
||||||
|
addr = (- addr) & BITS(15);
|
||||||
|
if (opcode <= 077 && addr > BITS(12)) {
|
||||||
|
if (addr < 070000) {
|
||||||
|
/*printf ("Bad short address: %o\n", addr);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
opcode |= 0100;
|
||||||
|
addr &= BITS(12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reg = 0;
|
||||||
|
cptr = skip_spaces (cptr); /* absorb spaces */
|
||||||
|
if (*cptr == '(') {
|
||||||
|
/* Индекс-регистр в скобках. */
|
||||||
|
cptr = besm6_parse_octal (cptr+1, ®);
|
||||||
|
if (! cptr || reg > 15) {
|
||||||
|
/*printf ("Bad register: %o\n", reg);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cptr = skip_spaces (cptr); /* absorb spaces */
|
||||||
|
if (*cptr != ')') {
|
||||||
|
/*printf ("No closing brace\n");*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
++cptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*val = reg << 20 | opcode << 12 | addr;
|
||||||
|
return cptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instruction parse: two commands per word.
|
||||||
|
*/
|
||||||
|
t_stat parse_instruction_word (char *cptr, t_value *val)
|
||||||
|
{
|
||||||
|
uint32 left, right;
|
||||||
|
|
||||||
|
*val = 0;
|
||||||
|
cptr = parse_instruction (cptr, &left);
|
||||||
|
if (! cptr)
|
||||||
|
return SCPE_ARG;
|
||||||
|
right = 0;
|
||||||
|
cptr = skip_spaces (cptr);
|
||||||
|
if (*cptr == ',') {
|
||||||
|
cptr = parse_instruction (cptr + 1, &right);
|
||||||
|
if (! cptr)
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
cptr = skip_spaces (cptr); /* absorb spaces */
|
||||||
|
if (*cptr != 0 && *cptr != ';' && *cptr != '\n' && *cptr != '\r') {
|
||||||
|
/*printf ("Extra symbols at eoln: %s\n", cptr);*/
|
||||||
|
return SCPE_2MARG;
|
||||||
|
}
|
||||||
|
*val = (t_value) left << 24 | right;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Печать машинной инструкции с мнемоникой.
|
||||||
|
*/
|
||||||
|
void besm6_fprint_cmd (FILE *of, uint32 cmd)
|
||||||
|
{
|
||||||
|
int reg, opcode, addr;
|
||||||
|
|
||||||
|
reg = (cmd >> 20) & 017;
|
||||||
|
if (cmd & BBIT(20)) {
|
||||||
|
opcode = (cmd >> 12) & 0370;
|
||||||
|
addr = cmd & BITS(15);
|
||||||
|
} else {
|
||||||
|
opcode = (cmd >> 12) & 077;
|
||||||
|
addr = cmd & 07777;
|
||||||
|
if (cmd & BBIT(19))
|
||||||
|
addr |= 070000;
|
||||||
|
}
|
||||||
|
fprintf (of, "%s", besm6_opname (opcode));
|
||||||
|
if (addr) {
|
||||||
|
fprintf (of, " ");
|
||||||
|
if (addr >= 077700)
|
||||||
|
fprintf (of, "-%o", (addr ^ 077777) + 1);
|
||||||
|
else
|
||||||
|
fprintf (of, "%o", addr);
|
||||||
|
}
|
||||||
|
if (reg) {
|
||||||
|
if (! addr)
|
||||||
|
fprintf (of, " ");
|
||||||
|
fprintf (of, "(%o)", reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Печать машинной инструкции в восьмеричном виде.
|
||||||
|
*/
|
||||||
|
void besm6_fprint_insn (FILE *of, uint32 insn)
|
||||||
|
{
|
||||||
|
if (insn & BBIT(20))
|
||||||
|
fprintf (of, "%02o %02o %05o ",
|
||||||
|
insn >> 20, (insn >> 15) & 037, insn & BITS(15));
|
||||||
|
else
|
||||||
|
fprintf (of, "%02o %03o %04o ",
|
||||||
|
insn >> 20, (insn >> 12) & 0177, insn & 07777);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbolic decode
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* *of = output stream
|
||||||
|
* addr = current PC
|
||||||
|
* *val = pointer to data
|
||||||
|
* *uptr = pointer to unit
|
||||||
|
* sw = switches
|
||||||
|
* Outputs:
|
||||||
|
* return = status code
|
||||||
|
*/
|
||||||
|
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw)
|
||||||
|
{
|
||||||
|
t_value cmd;
|
||||||
|
|
||||||
|
if (uptr && (uptr != &cpu_unit)) /* must be CPU */
|
||||||
|
return SCPE_ARG;
|
||||||
|
|
||||||
|
cmd = val[0];
|
||||||
|
|
||||||
|
|
||||||
|
if (sw & SWMASK ('M')) { /* symbolic decode? */
|
||||||
|
if (sw & SIM_SW_STOP && addr == PC && !(RUU & RUU_RIGHT_INSTR))
|
||||||
|
fprintf (of, "-> ");
|
||||||
|
besm6_fprint_cmd (of, (uint32)(cmd >> 24));
|
||||||
|
if (sw & SIM_SW_STOP) /* stop point */
|
||||||
|
fprintf (of, ", ");
|
||||||
|
else
|
||||||
|
fprintf (of, ",\n\t");
|
||||||
|
if (sw & SIM_SW_STOP && addr == PC && (RUU & RUU_RIGHT_INSTR))
|
||||||
|
fprintf (of, "-> ");
|
||||||
|
besm6_fprint_cmd (of, cmd & BITS(24));
|
||||||
|
|
||||||
|
} else if (sw & SWMASK ('I')) {
|
||||||
|
besm6_fprint_insn (of, (cmd >> 24) & BITS(24));
|
||||||
|
besm6_fprint_insn (of, cmd & BITS(24));
|
||||||
|
} else if (sw & SWMASK ('F')) {
|
||||||
|
fprintf (of, "%#.2g", besm6_to_ieee(cmd));
|
||||||
|
} else if (sw & SWMASK ('B')) {
|
||||||
|
fprintf (of, "%03o %03o %03o %03o %03o %03o",
|
||||||
|
(int) (cmd >> 40) & 0377,
|
||||||
|
(int) (cmd >> 32) & 0377,
|
||||||
|
(int) (cmd >> 24) & 0377,
|
||||||
|
(int) (cmd >> 16) & 0377,
|
||||||
|
(int) (cmd >> 8) & 0377,
|
||||||
|
(int) cmd & 0377);
|
||||||
|
} else if (sw & SWMASK ('X')) {
|
||||||
|
fprintf (of, "%013llx", cmd);
|
||||||
|
} else
|
||||||
|
fprintf (of, "%04o %04o %04o %04o",
|
||||||
|
(int) (cmd >> 36) & 07777,
|
||||||
|
(int) (cmd >> 24) & 07777,
|
||||||
|
(int) (cmd >> 12) & 07777,
|
||||||
|
(int) cmd & 07777);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbolic input
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* *cptr = pointer to input string
|
||||||
|
* addr = current PC
|
||||||
|
* *uptr = pointer to unit
|
||||||
|
* *val = pointer to output values
|
||||||
|
* sw = switches
|
||||||
|
* Outputs:
|
||||||
|
* status = error status
|
||||||
|
*/
|
||||||
|
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
if (uptr && (uptr != &cpu_unit)) /* must be CPU */
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (! parse_instruction_word (cptr, val)) /* symbolic parse? */
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
val[0] = 0;
|
||||||
|
for (i=0; i<16; i++) {
|
||||||
|
if (*cptr < '0' || *cptr > '7')
|
||||||
|
break;
|
||||||
|
val[0] = (val[0] << 3) | (*cptr - '0');
|
||||||
|
cptr = skip_spaces (cptr+1); /* next char */
|
||||||
|
}
|
||||||
|
if (*cptr != 0 && *cptr != ';' && *cptr != '\n' && *cptr != '\r') {
|
||||||
|
/*printf ("Extra symbols at eoln: %s\n", cptr);*/
|
||||||
|
return SCPE_2MARG;
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Чтение строки входного файла.
|
||||||
|
* Форматы строк:
|
||||||
|
* п 76543 - адрес пуска
|
||||||
|
* в 12345 - адрес ввода
|
||||||
|
* ч -123.45e+6 - вещественное число
|
||||||
|
* с 0123 4567 0123 4567 - восьмеричное слово
|
||||||
|
* к 00 22 00000 00 010 0000 - команды
|
||||||
|
*/
|
||||||
|
t_stat besm6_read_line (FILE *input, int *type, t_value *val)
|
||||||
|
{
|
||||||
|
char buf [512], *p;
|
||||||
|
int i, c;
|
||||||
|
again:
|
||||||
|
if (! fgets (buf, sizeof (buf), input)) {
|
||||||
|
*type = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
p = skip_spaces (buf);
|
||||||
|
if (*p == '\n' || *p == ';')
|
||||||
|
goto again;
|
||||||
|
c = utf8_to_unicode (&p);
|
||||||
|
if (c == CYRILLIC_SMALL_LETTER_VE ||
|
||||||
|
c == CYRILLIC_CAPITAL_LETTER_VE ||
|
||||||
|
c == 'b' || c == 'B') {
|
||||||
|
/* Адрес размещения данных. */
|
||||||
|
*type = ':';
|
||||||
|
*val = strtol (p, 0, 8);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (c == CYRILLIC_SMALL_LETTER_PE ||
|
||||||
|
c == CYRILLIC_CAPITAL_LETTER_PE ||
|
||||||
|
c == 'p' || c == 'P') {
|
||||||
|
/* Стартовый адрес. */
|
||||||
|
*type = '@';
|
||||||
|
*val = strtol (p, 0, 8);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (c == CYRILLIC_SMALL_LETTER_CHE ||
|
||||||
|
c == CYRILLIC_CAPITAL_LETTER_CHE ||
|
||||||
|
c == 'f' || c == 'F') {
|
||||||
|
/* Вещественное число. */
|
||||||
|
*type = '=';
|
||||||
|
*val = ieee_to_besm6 (strtod (p, 0));
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (c == CYRILLIC_SMALL_LETTER_ES ||
|
||||||
|
c == CYRILLIC_CAPITAL_LETTER_ES ||
|
||||||
|
c == 'c' || c == 'C') {
|
||||||
|
/* Восьмеричное слово. */
|
||||||
|
*type = '=';
|
||||||
|
*val = 0;
|
||||||
|
for (i=0; i<16; ++i) {
|
||||||
|
p = skip_spaces (p);
|
||||||
|
if (*p < '0' || *p > '7') {
|
||||||
|
if (i == 0) {
|
||||||
|
/* слишком короткое слово */
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*val = *val << 3 | (*p++ - '0');
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (c == CYRILLIC_SMALL_LETTER_KA ||
|
||||||
|
c == CYRILLIC_CAPITAL_LETTER_KA ||
|
||||||
|
c == 'k' || c == 'K') {
|
||||||
|
/* Команда. */
|
||||||
|
*type = '*';
|
||||||
|
if (parse_instruction_word (p, val) != SCPE_OK)
|
||||||
|
goto bad;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
/* Неверная строка входного файла */
|
||||||
|
bad: besm6_log ("Invalid input line: %s", buf);
|
||||||
|
return SCPE_FMT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load memory from file.
|
||||||
|
*/
|
||||||
|
t_stat besm6_load (FILE *input)
|
||||||
|
{
|
||||||
|
int addr, type;
|
||||||
|
t_value word;
|
||||||
|
t_stat err;
|
||||||
|
|
||||||
|
addr = 1;
|
||||||
|
PC = 1;
|
||||||
|
for (;;) {
|
||||||
|
err = besm6_read_line (input, &type, &word);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
switch (type) {
|
||||||
|
case 0: /* EOF */
|
||||||
|
return SCPE_OK;
|
||||||
|
case ':': /* address */
|
||||||
|
addr = (int)word;
|
||||||
|
break;
|
||||||
|
case '=': /* word */
|
||||||
|
if (addr < 010)
|
||||||
|
pult [addr] = SET_CONVOL (word, CONVOL_NUMBER);
|
||||||
|
else
|
||||||
|
memory [addr] = SET_CONVOL (word, CONVOL_NUMBER);
|
||||||
|
++addr;
|
||||||
|
break;
|
||||||
|
case '*': /* instruction */
|
||||||
|
if (addr < 010)
|
||||||
|
pult [addr] = SET_CONVOL (word, CONVOL_INSN);
|
||||||
|
else
|
||||||
|
memory [addr] = SET_CONVOL (word, CONVOL_INSN);
|
||||||
|
++addr;
|
||||||
|
break;
|
||||||
|
case '@': /* start address */
|
||||||
|
PC = (uint32)word;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (addr > MEMSIZE)
|
||||||
|
return SCPE_FMT;
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump memory to file.
|
||||||
|
*/
|
||||||
|
t_stat besm6_dump (FILE *of, char *fnam)
|
||||||
|
{
|
||||||
|
int addr, last_addr = -1;
|
||||||
|
t_value word;
|
||||||
|
|
||||||
|
fprintf (of, "; %s\n", fnam);
|
||||||
|
for (addr=1; addr<MEMSIZE; ++addr) {
|
||||||
|
if (addr < 010)
|
||||||
|
word = pult [addr];
|
||||||
|
else
|
||||||
|
word = memory [addr];
|
||||||
|
if (word == 0)
|
||||||
|
continue;
|
||||||
|
if (addr != last_addr+1) {
|
||||||
|
fprintf (of, "\nв %05o\n", addr);
|
||||||
|
}
|
||||||
|
last_addr = addr;
|
||||||
|
if (IS_INSN (word)) {
|
||||||
|
fprintf (of, "к ");
|
||||||
|
besm6_fprint_cmd (of, (uint32)(word >> 24));
|
||||||
|
fprintf (of, ", ");
|
||||||
|
besm6_fprint_cmd (of, word & BITS(24));
|
||||||
|
fprintf (of, "\t\t; %05o - ", addr);
|
||||||
|
fprintf (of, "%04o %04o %04o %04o\n",
|
||||||
|
(int) (word >> 36) & 07777,
|
||||||
|
(int) (word >> 24) & 07777,
|
||||||
|
(int) (word >> 12) & 07777,
|
||||||
|
(int) word & 07777);
|
||||||
|
} else {
|
||||||
|
fprintf (of, "с %04o %04o %04o %04o",
|
||||||
|
(int) (word >> 36) & 07777,
|
||||||
|
(int) (word >> 24) & 07777,
|
||||||
|
(int) (word >> 12) & 07777,
|
||||||
|
(int) word & 07777);
|
||||||
|
fprintf (of, "\t\t; %05o\n", addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loader/dumper
|
||||||
|
*/
|
||||||
|
t_stat sim_load (FILE *fi, char *cptr, char *fnam, int dump_flag)
|
||||||
|
{
|
||||||
|
if (dump_flag)
|
||||||
|
return besm6_dump (fi, fnam);
|
||||||
|
|
||||||
|
return besm6_load (fi);
|
||||||
|
}
|
1256
BESM6/besm6_tty.c
Normal file
1256
BESM6/besm6_tty.c
Normal file
File diff suppressed because it is too large
Load diff
484
BESM6/boot_dispak.b6
Normal file
484
BESM6/boot_dispak.b6
Normal file
|
@ -0,0 +1,484 @@
|
||||||
|
; boot_dispak.b6
|
||||||
|
п 2000
|
||||||
|
|
||||||
|
; Использование клавиатуры пульта БРУС при вызове ОС ДИСПАК.
|
||||||
|
;
|
||||||
|
; ТР2: 32, 31, 26 и 25-й разряды = '1' - при работе с ЭНМД-3,
|
||||||
|
; либо - 33 и 27-й разряды = '1' - при работе с ЭНМД-4;
|
||||||
|
; 000 000 000 000 000 011 000 011 000 000 000 000 000 000 000 000 ЭНМД-3
|
||||||
|
; 3 0 3
|
||||||
|
; 000 000 000 000 000 100 000 100 000 000 000 000 000 000 000 000 ЭНМД-4
|
||||||
|
; 4 0 4
|
||||||
|
в 2
|
||||||
|
с 0000 0303 0000 0000
|
||||||
|
|
||||||
|
; ТРЗ: 24 ÷ 17 и 4-й разряды = '1' - для чистки каталогов ОС;
|
||||||
|
; 000 000 000 000 000 000 000 000 111 111 110 000 000 000 001 000
|
||||||
|
; 7 7 6 0 0 0 1 0
|
||||||
|
;с 7760 0010
|
||||||
|
с 0
|
||||||
|
|
||||||
|
в 02000
|
||||||
|
к рег 101, уиа 2260(2) ; 02000 - 0002 0101 1240 2260
|
||||||
|
к уиа 2502(12), уиа -56(6) ; 02001 - 5240 2502 3247 7722
|
||||||
|
к сч 2537, зп 2605 ; 02002 - 0010 2537 0000 2605
|
||||||
|
к сда 101, зп 2664(6) ; 02003 - 0036 0101 3000 2664
|
||||||
|
к цикл 2003(6), уиа -2(1) ; 02004 - 3370 2003 0647 7776
|
||||||
|
к сч 2521(1), зп 502(1) ; 02005 - 0410 2521 0400 0502
|
||||||
|
к цикл 2005(1), уиа -2(6) ; 02006 - 0770 2005 3247 7776
|
||||||
|
к уиа (13), сч ; 02007 - 5640 0000 0010 0000
|
||||||
|
к слц 2546(6), цикл 2010(6) ; 02010 - 3013 2546 3370 2010
|
||||||
|
к нтж, по 2070 ; 02011 - 0012 0000 0260 2070
|
||||||
|
к уиа 2444(5), пв 2346(10) ; 02012 - 2640 2444 4310 2346
|
||||||
|
к нтж 2543, пе 2345 ; 02013 - 0012 2543 0270 2345
|
||||||
|
к сч 2, пб 3000 ; 02014 - 0010 0002 0300 3000
|
||||||
|
к сда 136, и 2427 ; 02015 - 0036 0136 0011 2427
|
||||||
|
к по 2017, вч 2664 ; 02016 - 0260 2017 0005 2664
|
||||||
|
к уи 16, уии 3(16) ; 02017 - 0040 0016 7044 0003
|
||||||
|
к сли 16(16), сли 16(3) ; 02020 - 7045 0016 1445 0016
|
||||||
|
к уиа -2(3), мода ; 02021 - 1647 7776 0220 0000
|
||||||
|
к мода (16), сч 2546(3) ; 02022 - 7220 0000 1410 2546
|
||||||
|
к зп 1777(3), цикл 2022(3) ; 02023 - 1400 1777 1770 2022
|
||||||
|
к уиа -1(3), мода ; 02024 - 1647 7777 0220 0000
|
||||||
|
к сч 1776, пио 2027(3) ; 02025 - 0010 1776 1740 2027
|
||||||
|
к сда 110, мода ; 02026 - 0036 0110 0220 0000
|
||||||
|
к сда 50, зп 1033(3) ; 02027 - 0036 0050 1400 1033
|
||||||
|
к сч 1775, сда 115 ; 02030 - 0010 1775 0036 0115
|
||||||
|
к пио 2032(3), сда 120 ; 02031 - 1740 2032 0036 0120
|
||||||
|
к и 2540, сда 70 ; 02032 - 0011 2540 0036 0070
|
||||||
|
к или 1033(3), зп 1033(3) ; 02033 - 1415 1033 1400 1033
|
||||||
|
к сч 1777, пио 2036(3) ; 02034 - 0010 1777 1740 2036
|
||||||
|
к сда 110, мода ; 02035 - 0036 0110 0220 0000
|
||||||
|
к и 2541, или 1033(3) ; 02036 - 0011 2541 1415 1033
|
||||||
|
к зп 1033(3), цикл 2025(3) ; 02037 - 1400 1033 1770 2025
|
||||||
|
к уиа 3(16), уиа -1(3) ; 02040 - 7240 0003 1647 7777
|
||||||
|
к сч, зп 1773 ; 02041 - 0010 0000 0000 1773
|
||||||
|
к уиа 10(7), мода ; 02042 - 3640 0010 0220 0000
|
||||||
|
к уиа -1(15), уиа -7(14) ; 02043 - 6647 7777 6247 7771
|
||||||
|
к сч 1777(3), слиа 1(15) ; 02044 - 1410 1777 6650 0001
|
||||||
|
к сда 140(7), и 2655(15) ; 02045 - 3436 0140 6411 2655
|
||||||
|
к по 2060, счи 15 ; 02046 - 0260 2060 0042 0015
|
||||||
|
к нтж 2415, уи 17 ; 02047 - 0012 2415 0040 0017
|
||||||
|
к сда 71, или 2532 ; 02050 - 0036 0071 0015 2532
|
||||||
|
к зп 1774, сч 1773 ; 02051 - 0000 1774 0010 1773
|
||||||
|
к сда 33, или 1774 ; 02052 - 0036 0033 0015 1774
|
||||||
|
к зп 1774, пв 2126(11) ; 02053 - 0000 1774 4710 2126
|
||||||
|
к сч 2534, и 2615 ; 02054 - 0010 2534 0011 2615
|
||||||
|
к по 2074, сч 2534 ; 02055 - 0260 2074 0010 2534
|
||||||
|
к сда 114, нтж 1775 ; 02056 - 0036 0114 0012 1775
|
||||||
|
к и 2423, по 2076 ; 02057 - 0011 2423 0260 2076
|
||||||
|
к цикл 2044(14), слиа -10(7) ; 02060 - 6370 2044 3657 7770
|
||||||
|
к сч 1773, слц 2664 ; 02061 - 0010 1773 0013 2664
|
||||||
|
к зп 1773, сда 102 ; 02062 - 0000 1773 0036 0102
|
||||||
|
к по 2043, пио 2066(3) ; 02063 - 0260 2043 1740 2066
|
||||||
|
к уиа 4(16), уиа (3) ; 02064 - 7240 0004 1640 0000
|
||||||
|
к пб 2041, мода ; 02065 - 0300 2041 0220 0000
|
||||||
|
к уиа 2502(5), пв 2367(7) ; 02066 - 2640 2502 3710 2367
|
||||||
|
к стоп, пб 2040 ; 02067 - 0330 0000 0300 2040
|
||||||
|
к уиа -35(16), уиа 1(13) ; 02070 - 7247 7743 5640 0001
|
||||||
|
к сч 72035(16), зп 2601(16) ; 02071 - 7110 2035 7000 2601
|
||||||
|
к цикл 2071(16), пв 2346(10) ; 02072 - 7370 2071 4310 2346
|
||||||
|
к зп 2543, пб 2014 ; 02073 - 0000 2543 0300 2014
|
||||||
|
к сч 2534, нтж 1775 ; 02074 - 0010 2534 0012 1775
|
||||||
|
к и 2423, пе 2060 ; 02075 - 0011 2423 0270 2060
|
||||||
|
к счи 17, сда 71 ; 02076 - 0042 0017 0036 0071
|
||||||
|
к или 2420, зп 1774 ; 02077 - 0015 2420 0000 1774
|
||||||
|
к счи 16, сда 76 ; 02100 - 0042 0016 0036 0076
|
||||||
|
к слц 1773, сда 33 ; 02101 - 0013 1773 0036 0033
|
||||||
|
к или 1774, пб 2105 ; 02102 - 0015 1774 0300 2105
|
||||||
|
к уиа 2257(11), мода ; 02103 - 4640 2257 0220 0000
|
||||||
|
к уиа 2106(2), сч 1027 ; 02104 - 1240 2106 0010 1027
|
||||||
|
к зп 1774, пб (2) ; 02105 - 0000 1774 1300 0000
|
||||||
|
к сч 1774, сда 147 ; 02106 - 0010 1774 0036 0147
|
||||||
|
к уи 16, сч 1774 ; 02107 - 0040 0016 0010 1774
|
||||||
|
к сда 107, и 2415 ; 02110 - 0036 0107 0011 2415
|
||||||
|
к уи 17, нтж 2415 ; 02111 - 0040 0017 0012 2415
|
||||||
|
к уи 15, сч 1774 ; 02112 - 0040 0015 0010 1774
|
||||||
|
к сда 145, и 2416 ; 02113 - 0036 0145 0011 2416
|
||||||
|
к сда 75, уи 6 ; 02114 - 0036 0075 0040 0006
|
||||||
|
к сли 6(17), сч 1027(16) ; 02115 - 7445 0006 7010 1027
|
||||||
|
к и 2625(6), уиа (1) ; 02116 - 3011 2625 0640 0000
|
||||||
|
к по 2120, уиа 2(1) ; 02117 - 0260 2120 0640 0002
|
||||||
|
к сч 1775, мода ; 02120 - 0010 1775 0220 0000
|
||||||
|
к сда 130, слц 2531 ; 02121 - 0036 0130 0013 2531
|
||||||
|
к и 2526, мода ; 02122 - 0011 2526 0220 0000
|
||||||
|
к сда 77(1), зп 2527 ; 02123 - 0436 0077 0000 2527
|
||||||
|
к счмр, сда 146 ; 02124 - 0031 0000 0036 0146
|
||||||
|
к и 2653, зп 2604 ; 02125 - 0011 2653 0000 2604
|
||||||
|
к сч, рег 37 ; 02126 - 0010 0000 0002 0037
|
||||||
|
к сч 2417, увв 20(16) ; 02127 - 0010 2417 7033 0020
|
||||||
|
к уи, сч 1774 ; 02130 - 0040 0000 0010 1774
|
||||||
|
к сда 145, и 2416 ; 02131 - 0036 0145 0011 2416
|
||||||
|
к или 2654, или 2653 ; 02132 - 0015 2654 0015 2653
|
||||||
|
к увв 20(16), уи ; 02133 - 7033 0020 0040 0000
|
||||||
|
к рег 237, и 2625(16) ; 02134 - 0002 0237 7011 2625
|
||||||
|
к по 2134, сч 2661 ; 02135 - 0260 2134 0010 2661
|
||||||
|
к увв 20(16), уи ; 02136 - 7033 0020 0040 0000
|
||||||
|
к уи, рег 37 ; 02137 - 0040 0000 0002 0037
|
||||||
|
к уиа 2147(6), уиа 11(4) ; 02140 - 3240 2147 2240 0011
|
||||||
|
к сч 2655(15), пио 2143(1) ; 02141 - 6410 2655 0740 2143
|
||||||
|
к или 2604, мода ; 02142 - 0015 2604 0220 0000
|
||||||
|
к или 2421, увв 20(16) ; 02143 - 0015 2421 7033 0020
|
||||||
|
к уи, счи 4 ; 02144 - 0040 0000 0042 0004
|
||||||
|
к увв 20(16), уи ; 02145 - 7033 0020 0040 0000
|
||||||
|
к увв 4000(16), пб (6) ; 02146 - 7033 4000 3300 0000
|
||||||
|
к и 2654, уиа 2430(5) ; 02147 - 0011 2654 2640 2430
|
||||||
|
к по 2412, уиа -7(6) ; 02150 - 0260 2412 3247 7771
|
||||||
|
к сч, мода ; 02151 - 0010 0000 0220 0000
|
||||||
|
к мод 2521(16), зп 7(6) ; 02152 - 7230 2521 3000 0007
|
||||||
|
к цикл 2152(6), уиа -7(6) ; 02153 - 3370 2152 3247 7771
|
||||||
|
к зп 1, цикл 2154(6) ; 02154 - 0000 0001 3370 2154
|
||||||
|
к сч 1774, увв (16) ; 02155 - 0010 1774 7033 0000
|
||||||
|
к сч 2416, или 2422 ; 02156 - 0010 2416 0015 2422
|
||||||
|
к увв 20(16), уи ; 02157 - 7033 0020 0040 0000
|
||||||
|
к сч 2527, или 2651 ; 02160 - 0010 2527 0015 2651
|
||||||
|
к уи, увв 20(16) ; 02161 - 0040 0000 7033 0020
|
||||||
|
к уи, увв ; 02162 - 0040 0000 0033 0000
|
||||||
|
к уиа -50(6), мода ; 02163 - 3247 7730 0220 0000
|
||||||
|
к зп 1, цикл 2164(6) ; 02164 - 0000 0001 3370 2164
|
||||||
|
к сч, уи ; 02165 - 0010 0000 0040 0000
|
||||||
|
к рег 37, уиа 76030(6) ; 02166 - 0002 0037 3247 6030
|
||||||
|
к уиа 77540(10), мода ; 02167 - 4247 7540 0220 0000
|
||||||
|
к сбр, рег 237 ; 02170 - 0020 0000 0002 0237
|
||||||
|
к и 2625(16), пе 2175 ; 02171 - 7011 2625 0270 2175
|
||||||
|
к цикл 2170(10), цикл 2167(6) ; 02172 - 4370 2170 3370 2167
|
||||||
|
к стоп, уиа 2126(7) ; 02173 - 0330 0000 3640 2126
|
||||||
|
к уиа 2474(5), пб 2366 ; 02174 - 2640 2474 0300 2366
|
||||||
|
к уиа 11(4), пв 2144(6) ; 02175 - 2240 0011 3310 2144
|
||||||
|
к зп 2533, и 2651 ; 02176 - 0000 2533 0011 2651
|
||||||
|
к пе 2351, увв 4035 ; 02177 - 0270 2351 0033 4035
|
||||||
|
к и 2655(16), уиа 2436(5) ; 02200 - 7011 2655 2640 2436
|
||||||
|
к пе 2412, уиа 1(10) ; 02201 - 0270 2412 4240 0001
|
||||||
|
к уиа 2206(6), уиа 2206(5) ; 02202 - 3240 2206 2640 2206
|
||||||
|
к сч 2424, уи 21 ; 02203 - 0010 2424 0040 0021
|
||||||
|
к мод 2521(16), сч (10) ; 02204 - 7230 2521 4010 0000
|
||||||
|
к уи, пб (6) ; 02205 - 0040 0000 3300 0000
|
||||||
|
к зп 2534, и 2535 ; 02206 - 0000 2534 0011 2535
|
||||||
|
к нтж 2536, уиа 2460(5) ; 02207 - 0012 2536 2640 2460
|
||||||
|
к пе 2412, сч 1774 ; 02210 - 0270 2412 0010 1774
|
||||||
|
к и 2660, пе 2302 ; 02211 - 0011 2660 0270 2302
|
||||||
|
к сч 2533, и 2652 ; 02212 - 0010 2533 0011 2652
|
||||||
|
к уиа 2444(5), пе 2366 ; 02213 - 2640 2444 0270 2366
|
||||||
|
к уиа -3(4), уиа (12) ; 02214 - 2247 7775 5240 0000
|
||||||
|
к счи 11, нтж 2530 ; 02215 - 0042 0011 0012 2530
|
||||||
|
к пе 2217, слиа 2000(12) ; 02216 - 0270 2217 5250 2000
|
||||||
|
к сч 2534, и 2614 ; 02217 - 0010 2534 0011 2614
|
||||||
|
к пе 2240, уиа -1(10) ; 02220 - 0270 2240 4247 7777
|
||||||
|
к уиа 2411(5), сч 2424 ; 02221 - 2640 2411 0010 2424
|
||||||
|
к уи 21, уиа 77401(6) ; 02222 - 0040 0021 3247 7401
|
||||||
|
к слиа 2(10), сч ; 02223 - 4250 0002 0010 0000
|
||||||
|
к мода 70000(12), слц 377(6) ; 02224 - 5227 0000 3013 0377
|
||||||
|
к цикл 2224(6), зп 2534 ; 02225 - 3370 2224 0000 2534
|
||||||
|
к уиа 2227(5), пв 2203(6) ; 02226 - 2640 2227 3310 2203
|
||||||
|
к зп 2533, нтж 2534 ; 02227 - 0000 2533 0012 2534
|
||||||
|
к и 2423, пе 2250 ; 02230 - 0011 2423 0270 2250
|
||||||
|
к сч 2533, и 2615 ; 02231 - 0010 2533 0011 2615
|
||||||
|
к уиа 2444(5), по 2366 ; 02232 - 2640 2444 0260 2366
|
||||||
|
к слиа 400(12), мода ; 02233 - 5250 0400 0220 0000
|
||||||
|
к цикл 2221(4), уиа 2255(6) ; 02234 - 2370 2221 3240 2255
|
||||||
|
к сч 2425, уи 21 ; 02235 - 0010 2425 0040 0021
|
||||||
|
к сч 2417, увв 20(16) ; 02236 - 0010 2417 7033 0020
|
||||||
|
к уи, пб (6) ; 02237 - 0040 0000 3300 0000
|
||||||
|
к уиа 2411(5), сч 2424 ; 02240 - 2640 2411 0010 2424
|
||||||
|
к уи 21, уиа 76001(6) ; 02241 - 0040 0021 3247 6001
|
||||||
|
к сч, уиа 3(10) ; 02242 - 0010 0000 4240 0003
|
||||||
|
к мода 70000(12), слц 1777(6) ; 02243 - 5227 0000 3013 1777
|
||||||
|
к цикл 2243(6), зп 2534 ; 02244 - 3370 2243 0000 2534
|
||||||
|
к уиа 2246(5), пв 2203(6) ; 02245 - 2640 2246 3310 2203
|
||||||
|
к нтж 2534, пе 2213 ; 02246 - 0012 2534 0270 2213
|
||||||
|
к уиа 2255(6), пб 2235 ; 02247 - 3240 2255 0300 2235
|
||||||
|
к слиа -1(10), уиа 2252(5) ; 02250 - 4257 7777 2640 2252
|
||||||
|
к мода, пв 2203(6) ; 02251 - 0220 0000 3310 2203
|
||||||
|
к нтж 2534, и 2423 ; 02252 - 0012 2534 0011 2423
|
||||||
|
к пе 2213, слиа 1(10) ; 02253 - 0270 2213 4250 0001
|
||||||
|
к слиа 400(12), пб 2234 ; 02254 - 5250 0400 0300 2234
|
||||||
|
к сч, уи ; 02255 - 0010 0000 0040 0000
|
||||||
|
к рег 37, пб (11) ; 02256 - 0002 0037 4700 0000
|
||||||
|
к уиа 1(14), пб 2335 ; 02257 - 6240 0001 0300 2335
|
||||||
|
к зп 1027, сч 2516 ; 02260 - 0000 1027 0010 2516
|
||||||
|
к или 1775, зп 1775 ; 02261 - 0015 1775 0000 1775
|
||||||
|
к уиа 2265(11), пб 2104 ; 02262 - 4640 2265 0300 2104
|
||||||
|
к слиа 40(4), цикл 2272(14) ; 02263 - 2250 0040 6370 2272
|
||||||
|
к уиа 2466(5), пв 2367(7) ; 02264 - 2640 2466 3710 2367
|
||||||
|
к сч 2, сда 130 ; 02265 - 0010 0002 0036 0130
|
||||||
|
к и 2427, уиа -17(14) ; 02266 - 0011 2427 6247 7761
|
||||||
|
к уиа (2), уиа (4) ; 02267 - 1240 0000 2240 0000
|
||||||
|
к по 2271, вч 2664 ; 02270 - 0260 2271 0005 2664
|
||||||
|
к зп 2542, мода ; 02271 - 0000 2542 0220 0000
|
||||||
|
к уиа -37(7), сч 1775 ; 02272 - 3647 7741 0010 1775
|
||||||
|
к нтж 70000(4), и 2423 ; 02273 - 2112 0000 0011 2423
|
||||||
|
к пе 2263, сч 1775 ; 02274 - 0270 2263 0010 1775
|
||||||
|
к сда 155, нтж 70016(4) ; 02275 - 0036 0155 2112 0016
|
||||||
|
к и 2415, пе 2263 ; 02276 - 0011 2415 0270 2263
|
||||||
|
к счи 2, нтж 2542 ; 02277 - 0042 0002 0012 2542
|
||||||
|
к по 2303, слиа 1(2) ; 02300 - 0260 2303 1250 0001
|
||||||
|
к пб 2263, мода ; 02301 - 0300 2263 0220 0000
|
||||||
|
к уии 6(11), пб 2235 ; 02302 - 4444 0006 0300 2235
|
||||||
|
к мода (4), сч 70037(7) ; 02303 - 2220 0000 3510 0037
|
||||||
|
к зп 3537(7), цикл 2303(7) ; 02304 - 3400 3537 3770 2303
|
||||||
|
к сч 3502, зп 1775 ; 02305 - 0010 3502 0000 1775
|
||||||
|
к мода, пв 2040(2) ; 02306 - 0220 0000 1310 2040
|
||||||
|
к зп 1030, сч 3500 ; 02307 - 0000 1030 0010 3500
|
||||||
|
к зп 1775, сч 3 ; 02310 - 0000 1775 0010 0003
|
||||||
|
к и 2660, пб 2103 ; 02311 - 0011 2660 0300 2103
|
||||||
|
к уиа -2(14), сч 3515 ; 02312 - 6247 7776 0010 3515
|
||||||
|
к сда 117, зп 1775 ; 02313 - 0036 0117 0000 1775
|
||||||
|
к и 2423, по 2103 ; 02314 - 0011 2423 0260 2103
|
||||||
|
к сч 2663, пв 2123(11) ; 02315 - 0010 2663 4710 2123
|
||||||
|
к сч 3516, и 2415 ; 02316 - 0010 3516 0011 2415
|
||||||
|
к сда 75, уи 6 ; 02317 - 0036 0075 0040 0006
|
||||||
|
к сч 70000(6), нтж 3516 ; 02320 - 3110 0000 0012 3516
|
||||||
|
к и 2415, пе 2103 ; 02321 - 0011 2415 0270 2103
|
||||||
|
к мода (6), сч 70002(14) ; 02322 - 3220 0000 6110 0002
|
||||||
|
к зп 2604(14), цикл 2322(14) ; 02323 - 6000 2604 6370 2322
|
||||||
|
к уиа 2510(12), пв 2040(2) ; 02324 - 5240 2510 1310 2040
|
||||||
|
к уиа -2(14), пв 2126(11) ; 02325 - 6247 7776 4710 2126
|
||||||
|
к сч 70002(14), нтж 2604(14) ; 02326 - 6110 0002 6012 2604
|
||||||
|
к уиа 2257(11), пе 2103 ; 02327 - 4640 2257 0270 2103
|
||||||
|
к цикл 2326(14), уиа -22(14) ; 02330 - 6370 2326 6247 7756
|
||||||
|
к сч 70026(14), зп 1026(14) ; 02331 - 6110 0026 6000 1026
|
||||||
|
к цикл 2331(14), уиа 2335(11) ; 02332 - 6370 2331 4640 2335
|
||||||
|
к сч 1774, зп 1031 ; 02333 - 0010 1774 0000 1031
|
||||||
|
к пб 2104, мода ; 02334 - 0300 2104 0220 0000
|
||||||
|
к сч 1774, слц 2650 ; 02335 - 0010 1774 0013 2650
|
||||||
|
к зп 1774, сч 1775 ; 02336 - 0000 1774 0010 1775
|
||||||
|
к слц 2634, пв 2121(11) ; 02337 - 0013 2634 4710 2121
|
||||||
|
к сч 2522, зп 502 ; 02340 - 0010 2522 0000 0502
|
||||||
|
к уиа -37(6), мода ; 02341 - 3247 7741 0220 0000
|
||||||
|
к сч 3537(6), зп 71777(6) ; 02342 - 3010 3537 3100 1777
|
||||||
|
к цикл 2342(6), сч ; 02343 - 3370 2342 0010 0000
|
||||||
|
к зп 72000, пб 70000 ; 02344 - 0100 2000 0307 0000
|
||||||
|
к уиа 2345(7), пб 2367 ; 02345 - 3640 2345 0300 2367
|
||||||
|
к уиа -2(3), сч ; 02346 - 1647 7776 0010 0000
|
||||||
|
к слц 2546(3), цикл 2347(3) ; 02347 - 1413 2546 1770 2347
|
||||||
|
к пб (10), мода ; 02350 - 4300 0000 0220 0000
|
||||||
|
к сч 1774, и 2660 ; 02351 - 0010 1774 0011 2660
|
||||||
|
к пе 2060, уиа 31(4) ; 02352 - 0270 2060 2240 0031
|
||||||
|
к мода, пв 2144(6) ; 02353 - 0220 0000 3310 2144
|
||||||
|
к зп 2534, сч 2533 ; 02354 - 0000 2534 0010 2533
|
||||||
|
к и 2654, по 2402 ; 02355 - 0011 2654 0260 2402
|
||||||
|
к сч 2534, и 2662 ; 02356 - 0010 2534 0011 2662
|
||||||
|
к уиа 2452(5), пе 2404 ; 02357 - 2640 2452 0270 2404
|
||||||
|
к сч 2534, и 2660 ; 02360 - 0010 2534 0011 2660
|
||||||
|
к уиа 2466(5), пе 2366 ; 02361 - 2640 2466 0270 2366
|
||||||
|
к сч 2534, и 2661 ; 02362 - 0010 2534 0011 2661
|
||||||
|
к пе 2410, сч 2534 ; 02363 - 0270 2410 0010 2534
|
||||||
|
к и 2652, уиа 2452(5) ; 02364 - 0011 2652 2640 2452
|
||||||
|
к пе 2366, уиа 2452(5) ; 02365 - 0270 2366 2640 2452
|
||||||
|
к уиа 2126(7), пв 2235(6) ; 02366 - 3640 2126 3310 2235
|
||||||
|
к уиа -10(10), мода ; 02367 - 4247 7770 0220 0000
|
||||||
|
к зп 1, цикл 2370(10) ; 02370 - 0000 0001 4370 2370
|
||||||
|
к сч, рег ; 02371 - 0010 0000 0002 0000
|
||||||
|
к уиа -5(10), мода ; 02372 - 4247 7773 0220 0000
|
||||||
|
к мода (5), сч 5(10) ; 02373 - 2620 0000 4010 0005
|
||||||
|
к рег 6(10), цикл 2373(10) ; 02374 - 4002 0006 4370 2373
|
||||||
|
к сч, рег 7 ; 02375 - 0010 0000 0002 0007
|
||||||
|
к уиа 76030(10), мода ; 02376 - 4247 6030 0220 0000
|
||||||
|
к уиа 77526(3), мода ; 02377 - 1647 7526 0220 0000
|
||||||
|
к сбр, цикл 2400(3) ; 02400 - 0020 0000 1770 2400
|
||||||
|
к цикл 2377(10), пб (7) ; 02401 - 4370 2377 3700 0000
|
||||||
|
к сч 2533, уиа 2430(5) ; 02402 - 0010 2533 2640 2430
|
||||||
|
к и 2653, по 2366 ; 02403 - 0011 2653 0260 2366
|
||||||
|
к уиа 1(4), пв 2144(6) ; 02404 - 2240 0001 3310 2144
|
||||||
|
к мода, пв 2235(6) ; 02405 - 0220 0000 3310 2235
|
||||||
|
к уиа 76030(10), пв 2377(7) ; 02406 - 4247 6030 3710 2377
|
||||||
|
к уиа 2126(7), пб 2367 ; 02407 - 3640 2126 0300 2367
|
||||||
|
к уиа 2452(5), пб 2366 ; 02410 - 2640 2452 0300 2366
|
||||||
|
к уиа 2126(6), пб 2235 ; 02411 - 3240 2126 0300 2235
|
||||||
|
к сч 1774, и 2660 ; 02412 - 0010 1774 0011 2660
|
||||||
|
к по 2366, пв 2235(6) ; 02413 - 0260 2366 3310 2235
|
||||||
|
к пб 2060, мода ; 02414 - 0300 2060 0220 0000
|
||||||
|
|
||||||
|
в 02415
|
||||||
|
с 0000 0000 0000 0007 ; 02415
|
||||||
|
с 0000 0000 0000 0003 ; 02416
|
||||||
|
с 0000 0000 0000 1050 ; 02417
|
||||||
|
с 0000 0000 0174 0000 ; 02420
|
||||||
|
с 0000 0000 0000 2400 ; 02421
|
||||||
|
с 0000 0000 0000 0000 ; 02422
|
||||||
|
с 0000 0000 0000 7777 ; 02423
|
||||||
|
с 0000 0000 0000 2003 ; 02424
|
||||||
|
с 0000 0000 0000 2013 ; 02425
|
||||||
|
с 0000 0000 0000 0000 ; 02426
|
||||||
|
с 0000 0000 0000 0017 ; 02427
|
||||||
|
с 2236 0400 4176 2000 ; 02430
|
||||||
|
с 2220 0400 4044 0000 ; 02431
|
||||||
|
с 2220 0400 4044 0000 ; 02432
|
||||||
|
с 3636 0400 4044 0000 ; 02433
|
||||||
|
с 2220 0400 4044 0000 ; 02434
|
||||||
|
с 2236 3700 7434 0000 ; 02435
|
||||||
|
с 0003 4376 2022 0000 ; 02436
|
||||||
|
с 0004 2222 2220 0000 ; 02437
|
||||||
|
с 0004 2222 2220 0000 ; 02440
|
||||||
|
с 0004 2222 2220 0000 ; 02441
|
||||||
|
с 0004 2222 2520 0000 ; 02442
|
||||||
|
с 0003 4222 3060 0000 ; 02443
|
||||||
|
с 3476 2046 3440 4000 ; 02444
|
||||||
|
с 4252 0044 4244 4000 ; 02445
|
||||||
|
с 4252 0044 4044 4000 ; 02446
|
||||||
|
с 4252 0070 4044 4000 ; 02447
|
||||||
|
с 4252 0044 4252 4000 ; 02450
|
||||||
|
с 3452 0046 3461 4000 ; 02451
|
||||||
|
с 0000 0021 0740 0000 ; 02452
|
||||||
|
с 0000 0021 0420 0000 ; 02453
|
||||||
|
с 0000 0037 0420 0000 ; 02454
|
||||||
|
с 0000 0021 0740 0000 ; 02455
|
||||||
|
с 0000 0021 0420 0000 ; 02456
|
||||||
|
с 0000 0017 0740 0000 ; 02457
|
||||||
|
с 2236 0046 6247 0040 ; 02460
|
||||||
|
с 2220 0044 2250 4040 ; 02461
|
||||||
|
с 2220 0044 2250 4040 ; 02462
|
||||||
|
с 3636 0070 2270 4740 ; 02463
|
||||||
|
с 2220 0044 2250 4440 ; 02464
|
||||||
|
с 2236 0046 1647 0440 ; 02465
|
||||||
|
с 0022 3604 0070 4440 ; 02466
|
||||||
|
с 0022 2004 0044 4440 ; 02467
|
||||||
|
с 0022 2004 0044 4470 ; 02470
|
||||||
|
с 0036 3604 0072 7444 ; 02471
|
||||||
|
с 0022 2004 0044 4444 ; 02472
|
||||||
|
с 0022 3637 0070 3470 ; 02473
|
||||||
|
с 2236 0400 3470 4044 ; 02474
|
||||||
|
с 2220 0400 4244 4440 ; 02475
|
||||||
|
с 2220 0400 4244 4440 ; 02476
|
||||||
|
с 3636 0400 4270 4440 ; 02477
|
||||||
|
с 2220 0400 4240 5240 ; 02500
|
||||||
|
с 2236 3700 3474 6140 ; 02501
|
||||||
|
с 4561 0213 7462 2422 ; 02502
|
||||||
|
с 4501 0211 1112 2420 ; 02503
|
||||||
|
с 4501 0251 1013 6434 ; 02504
|
||||||
|
с 7561 0251 1022 2422 ; 02505
|
||||||
|
с 4501 0251 1112 2422 ; 02506
|
||||||
|
с 4567 6330 7061 6734 ; 02507
|
||||||
|
с 0456 1021 3716 2240 ; 02510
|
||||||
|
с 0450 1021 1101 2240 ; 02511
|
||||||
|
с 0450 1025 1107 2270 ; 02512
|
||||||
|
с 0756 1025 1111 2244 ; 02513
|
||||||
|
с 0450 1025 1111 2244 ; 02514
|
||||||
|
с 0456 7633 0711 3670 ; 02515
|
||||||
|
с 0000 0757 0000 0000 ; 02516
|
||||||
|
с 0000 2523 0000 0000 ; 02517
|
||||||
|
с 0010 2425 0040 0021 ; 02520
|
||||||
|
с 0010 2523 2700 0000 ; 02521
|
||||||
|
с 0010 2523 1700 0000 ; 02522
|
||||||
|
с 0000 0000 0000 0000 ; 02523
|
||||||
|
с 0000 0000 0000 0030 ; 02524
|
||||||
|
с 0000 0000 0000 0040 ; 02525
|
||||||
|
с 0000 0000 0003 7777 ; 02526
|
||||||
|
с 0000 0000 0000 1334 ; 02527
|
||||||
|
с 0000 0000 0000 2340 ; 02530
|
||||||
|
с 0000 0000 0007 7775 ; 02531
|
||||||
|
с 0000 0000 0440 0020 ; 02532
|
||||||
|
с 0017 0707 4005 0513 ; 02533
|
||||||
|
с 1646 5273 4157 0513 ; 02534
|
||||||
|
с 0007 7777 0000 0000 ; 02535
|
||||||
|
с 0007 0707 0000 0000 ; 02536
|
||||||
|
с 4000 0000 0000 0000 ; 02537
|
||||||
|
с 0000 0000 0017 7777 ; 02540
|
||||||
|
с 0000 0000 0000 0377 ; 02541
|
||||||
|
с 0000 0000 0000 0000 ; 02542
|
||||||
|
с 2740 0000 0000 4007 ; 02543
|
||||||
|
с 3000 0000 0000 4005 ; 02544
|
||||||
|
с 7760 0000 0000 0000 ; 02545
|
||||||
|
с 7760 0000 0000 0000 ; 02546
|
||||||
|
с 3000 0000 0000 4005 ; 02547
|
||||||
|
с 7777 7400 0000 0000 ; 02550
|
||||||
|
с 7760 0000 0000 0000 ; 02551
|
||||||
|
с 3000 0000 0000 4005 ; 02552
|
||||||
|
с 7777 7400 0000 0000 ; 02553
|
||||||
|
с 0000 0000 0000 0000 ; 02554
|
||||||
|
|
||||||
|
в 02600
|
||||||
|
с 0000 0000 0000 0000 ; 02600
|
||||||
|
с 0000 0000 0000 0037 ; 02601
|
||||||
|
с 0000 0000 0742 1025 ; 02602
|
||||||
|
с 0000 0000 0021 0000 ; 02603
|
||||||
|
с 0000 0000 0000 0000 ; 02604
|
||||||
|
с 4000 0000 0000 0000 ; 02605
|
||||||
|
с 2000 0000 0000 0000 ; 02606
|
||||||
|
с 1000 0000 0000 0000 ; 02607
|
||||||
|
с 0400 0000 0000 0000 ; 02610
|
||||||
|
с 0200 0000 0000 0000 ; 02611
|
||||||
|
с 0100 0000 0000 0000 ; 02612
|
||||||
|
с 0040 0000 0000 0000 ; 02613
|
||||||
|
с 0020 0000 0000 0000 ; 02614
|
||||||
|
с 0010 0000 0000 0000 ; 02615
|
||||||
|
с 0004 0000 0000 0000 ; 02616
|
||||||
|
с 0002 0000 0000 0000 ; 02617
|
||||||
|
с 0001 0000 0000 0000 ; 02620
|
||||||
|
с 0000 4000 0000 0000 ; 02621
|
||||||
|
с 0000 2000 0000 0000 ; 02622
|
||||||
|
с 0000 1000 0000 0000 ; 02623
|
||||||
|
с 0000 0400 0000 0000 ; 02624
|
||||||
|
с 0000 0200 0000 0000 ; 02625
|
||||||
|
с 0000 0100 0000 0000 ; 02626
|
||||||
|
с 0000 0040 0000 0000 ; 02627
|
||||||
|
с 0000 0020 0000 0000 ; 02630
|
||||||
|
с 0000 0010 0000 0000 ; 02631
|
||||||
|
с 0000 0004 0000 0000 ; 02632
|
||||||
|
с 0000 0002 0000 0000 ; 02633
|
||||||
|
с 0000 0001 0000 0000 ; 02634
|
||||||
|
с 0000 0000 4000 0000 ; 02635
|
||||||
|
с 0000 0000 2000 0000 ; 02636
|
||||||
|
с 0000 0000 1000 0000 ; 02637
|
||||||
|
с 0000 0000 0400 0000 ; 02640
|
||||||
|
с 0000 0000 0200 0000 ; 02641
|
||||||
|
с 0000 0000 0100 0000 ; 02642
|
||||||
|
с 0000 0000 0040 0000 ; 02643
|
||||||
|
с 0000 0000 0020 0000 ; 02644
|
||||||
|
с 0000 0000 0010 0000 ; 02645
|
||||||
|
с 0000 0000 0004 0000 ; 02646
|
||||||
|
с 0000 0000 0002 0000 ; 02647
|
||||||
|
с 0000 0000 0001 0000 ; 02650
|
||||||
|
с 0000 0000 0000 4000 ; 02651
|
||||||
|
с 0000 0000 0000 2000 ; 02652
|
||||||
|
с 0000 0000 0000 1000 ; 02653
|
||||||
|
с 0000 0000 0000 0400 ; 02654
|
||||||
|
с 0000 0000 0000 0200 ; 02655
|
||||||
|
с 0000 0000 0000 0100 ; 02656
|
||||||
|
с 0000 0000 0000 0040 ; 02657
|
||||||
|
с 0000 0000 0000 0020 ; 02660
|
||||||
|
с 0000 0000 0000 0010 ; 02661
|
||||||
|
с 0000 0000 0000 0004 ; 02662
|
||||||
|
с 0000 0000 0000 0002 ; 02663
|
||||||
|
с 0000 0000 0000 0001 ; 02664
|
||||||
|
|
||||||
|
в 03000
|
||||||
|
к по 3002, мода ; 03000 - 0260 3002 0220 0000
|
||||||
|
к ржа 3, пб 2015 ; 03001 - 0037 0003 0300 2015
|
||||||
|
к уиа 3004(7), уиа 2466(5) ; 03002 - 3640 3004 2640 2466
|
||||||
|
к пб 2367, мода ; 03003 - 0300 2367 0220 0000
|
||||||
|
к слиа 1(1), пб 3004 ; 03004 - 0650 0001 0300 3004
|
||||||
|
|
||||||
|
в 03500
|
||||||
|
с 0000 0560 0000 4005 ; 03500
|
||||||
|
с 4000 0000 0000 4005 ; 03501
|
||||||
|
с 0000 0000 0000 4005 ; 03502
|
||||||
|
с 0000 0000 0000 4005 ; 03503
|
||||||
|
с 0000 0000 0000 0006 ; 03504
|
||||||
|
с 4000 0000 0000 0000 ; 03505
|
||||||
|
с 0000 0000 0000 3320 ; 03506
|
||||||
|
с 0000 0000 0000 0022 ; 03507
|
||||||
|
с 0000 0000 0000 0021 ; 03510
|
||||||
|
с 7760 0000 3760 0000 ; 03511
|
||||||
|
с 0000 0000 0000 0000 ; 03512
|
||||||
|
с 0000 0000 0000 0000 ; 03513
|
||||||
|
с 0000 0000 0000 0000 ; 03514
|
||||||
|
с 4000 0070 0004 0310 ; 03515
|
||||||
|
с 1770 0000 0000 0003 ; 03516
|
||||||
|
с 0000 0000 1600 4227 ; 03517
|
||||||
|
с 3722 1066 0361 6435 ; 03520
|
||||||
|
с 0000 0000 0000 0000 ; 03521
|
||||||
|
с 7760 0000 0000 0000 ; 03522
|
||||||
|
с 7760 0000 0000 3220 ; 03523
|
||||||
|
с 0000 0000 1022 4005 ; 03524
|
||||||
|
с 1240 0000 0000 0000 ; 03525
|
||||||
|
с 1313 1413 1413 1413 ; 03526
|
||||||
|
с 7777 4000 6000 0000 ; 03527
|
||||||
|
с 7403 0000 0000 0000 ; 03530
|
||||||
|
с 7777 7777 7777 7777 ; 03531
|
||||||
|
с 0000 0017 7760 0000 ; 03532
|
||||||
|
с 0000 0000 0000 0000 ; 03533
|
||||||
|
с 0000 0000 0000 0000 ; 03534
|
||||||
|
с 0000 0000 0000 0000 ; 03535
|
||||||
|
с 0000 0000 7760 0000 ; 03536
|
||||||
|
с 0000 0000 0000 0000 ; 03537
|
90
BESM6/dispak.ini
Normal file
90
BESM6/dispak.ini
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
set -n console log=log.txt
|
||||||
|
set console debug=log
|
||||||
|
set cpu idle
|
||||||
|
;set cpu debug
|
||||||
|
;set mmu debug
|
||||||
|
;set drum debug
|
||||||
|
;set disk debug
|
||||||
|
|
||||||
|
;
|
||||||
|
; Приводим барабаны в исходное состояние.
|
||||||
|
;
|
||||||
|
attach -n drum0 drum1x.bin
|
||||||
|
attach -n drum1 drum2x.bin
|
||||||
|
|
||||||
|
;
|
||||||
|
; Создаем рабочий диск.
|
||||||
|
;
|
||||||
|
attach -n disk6 2052.bin
|
||||||
|
|
||||||
|
;
|
||||||
|
; Подключаем диски.
|
||||||
|
;
|
||||||
|
attach -e disk7 sbor2053.bin
|
||||||
|
attach -e disk5 krab2063.bin
|
||||||
|
attach -e disk0 sbor2048.bin
|
||||||
|
attach -e disk1 svs2048.bin
|
||||||
|
attach -e disk2 alt2048.bin
|
||||||
|
|
||||||
|
;
|
||||||
|
; Подключаем АЦПУ.
|
||||||
|
;
|
||||||
|
attach prn0 output.txt
|
||||||
|
|
||||||
|
;
|
||||||
|
; Активируем операторский терминал,
|
||||||
|
; на который идут сообщения.
|
||||||
|
;
|
||||||
|
attach tty1 console
|
||||||
|
|
||||||
|
;
|
||||||
|
; Режимы по вкусу
|
||||||
|
;
|
||||||
|
;set tty1 jcuken,authbs
|
||||||
|
set tty1 qwerty,authbs
|
||||||
|
set -n tty1 log=tty1.txt
|
||||||
|
|
||||||
|
;
|
||||||
|
; Разрешаем подключение пользователей по telnet, порт 4199.
|
||||||
|
;
|
||||||
|
attach tty 4199
|
||||||
|
set tty2 authbs
|
||||||
|
set tty3 authbs
|
||||||
|
set tty4 authbs
|
||||||
|
set tty5 authbs
|
||||||
|
set tty6 authbs
|
||||||
|
set tty7 authbs
|
||||||
|
set tty8 authbs
|
||||||
|
set tty9 authbs
|
||||||
|
set tty10 authbs
|
||||||
|
set tty11 authbs
|
||||||
|
set tty12 authbs
|
||||||
|
set tty13 authbs
|
||||||
|
set tty14 authbs
|
||||||
|
set tty15 authbs
|
||||||
|
set tty16 authbs
|
||||||
|
set tty17 authbs
|
||||||
|
set tty18 authbs
|
||||||
|
set tty19 authbs
|
||||||
|
set tty20 authbs
|
||||||
|
set tty21 authbs
|
||||||
|
set tty22 authbs
|
||||||
|
set tty23 authbs
|
||||||
|
set tty24 authbs
|
||||||
|
|
||||||
|
;
|
||||||
|
; Включение БРС/БРЗ для совместимости.
|
||||||
|
; Замедляет работу на 20%.
|
||||||
|
;
|
||||||
|
;set mmu cache
|
||||||
|
|
||||||
|
;
|
||||||
|
; Запуск ОС ДИСПАК.
|
||||||
|
;
|
||||||
|
load boot_dispak.b6
|
||||||
|
|
||||||
|
; Происходит контроль числа по адресу 1031
|
||||||
|
d 1031 0
|
||||||
|
|
||||||
|
run 2000
|
||||||
|
;quit
|
30
BESM6/expect.ini
Executable file
30
BESM6/expect.ini
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
# Attaching the input device
|
||||||
|
at fs0 input.txt
|
||||||
|
# Waiting for the end of initial setup
|
||||||
|
expect -r "ДATA.*\n"
|
||||||
|
do dispak.ini
|
||||||
|
# Now we're ready to send commands from the front panel
|
||||||
|
echo Requesting input from the punch tape reader (FS8)
|
||||||
|
d 6 1
|
||||||
|
d 5 10
|
||||||
|
set cpu req
|
||||||
|
expect -r "Л0.*\n"
|
||||||
|
go
|
||||||
|
|
||||||
|
# The process had been started, check state every 10 model seconds
|
||||||
|
send after=1000000 "WCPP\r"
|
||||||
|
expect -p -r "4199.*\n" send after=10000000 "WCPP\r"; go
|
||||||
|
expect -c "HET\r\n" step 10000
|
||||||
|
go
|
||||||
|
echo Enabling the printer (ONL A0)
|
||||||
|
d 6 10
|
||||||
|
d 5 1
|
||||||
|
set cpu req
|
||||||
|
expect -r "ECT.*\n"
|
||||||
|
go
|
||||||
|
echo Checking for the printing to finish
|
||||||
|
send "HOMB\r"
|
||||||
|
expect -p -r "4199.*\n" send "HOMB\r"; go
|
||||||
|
expect -c "HET\r\n"
|
||||||
|
go
|
||||||
|
echo Done
|
53
BESM6/input.txt
Normal file
53
BESM6/input.txt
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
ШИФР 419999 ЗС5^
|
||||||
|
EEВ1А3
|
||||||
|
*NAME PRIME NUMBERS
|
||||||
|
* The ^L char before *NAME is important
|
||||||
|
* NO LIST Disable source listing by removing spaces between * and NO
|
||||||
|
*NO LOAD LIST Enable loader listing by adding 5 spaces between * and NO
|
||||||
|
* Disabling fanfold page alignment
|
||||||
|
*CALL NOTLIS
|
||||||
|
*ASSEM
|
||||||
|
ETIME: ,NAME,
|
||||||
|
c Get time of day in jiffies
|
||||||
|
,*53 , 010B
|
||||||
|
c OR the integer exponent
|
||||||
|
,AOX , =6400000000000000
|
||||||
|
c F.p. divide by 50
|
||||||
|
,A/X , =R50.0
|
||||||
|
c Return
|
||||||
|
13 ,UJ ,
|
||||||
|
,END ,
|
||||||
|
*FTN
|
||||||
|
PROGRAM MAIN
|
||||||
|
PRINT 1000
|
||||||
|
1000 FORMAT(' Computing prime numbers the dumb way')
|
||||||
|
TIME0 = ETIME(0)
|
||||||
|
CALL PRIMES
|
||||||
|
TIME1 = ETIME(0)
|
||||||
|
NTIME = TIME1 - TIME0
|
||||||
|
PRINT 2000, NTIME
|
||||||
|
STOP
|
||||||
|
2000 FORMAT (' Time, seconds =', i6)
|
||||||
|
end
|
||||||
|
|
||||||
|
SUBROUTINE PRIMES
|
||||||
|
T=0
|
||||||
|
DO 10 N=1001, 100000, 2
|
||||||
|
MAXK=SQRT(N+0.0)+1
|
||||||
|
DO 20 K=3, MAXK, 2
|
||||||
|
M = (N / K) * K
|
||||||
|
IF (N .EQ. M) GOTO 10
|
||||||
|
20 CONTINUE
|
||||||
|
c------ Printing every 1000th prime number
|
||||||
|
T=T+1
|
||||||
|
IF (T .LT. 1000) GOTO 10
|
||||||
|
PRINT 1000, N
|
||||||
|
T=0
|
||||||
|
10 CONTINUE
|
||||||
|
RETURN
|
||||||
|
1000 FORMAT (1X, I9)
|
||||||
|
END
|
||||||
|
*EXECUTE
|
||||||
|
* The ^L char after *END FILE is important
|
||||||
|
*END FILE
|
||||||
|
ЕКОНЕЦ
|
2425
BESM6/test_alu.b6
Normal file
2425
BESM6/test_alu.b6
Normal file
File diff suppressed because it is too large
Load diff
16
BESM6/test_alu.ini
Normal file
16
BESM6/test_alu.ini
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
! rm -f log.txt
|
||||||
|
;set console log=log.txt
|
||||||
|
;set console debug=log
|
||||||
|
;set cpu debug
|
||||||
|
;set mmu debug
|
||||||
|
|
||||||
|
set mmu cache
|
||||||
|
|
||||||
|
load test_alu.b6
|
||||||
|
|
||||||
|
echo Должно быть три останова подряд на адресе 32013.
|
||||||
|
br 32013
|
||||||
|
go 32000
|
||||||
|
go
|
||||||
|
go
|
||||||
|
;quit
|
16
BESM6/test_cu.ini
Normal file
16
BESM6/test_cu.ini
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
! rm -f log.txt
|
||||||
|
set console log=log.txt
|
||||||
|
set console debug=log
|
||||||
|
;set cpu debug
|
||||||
|
;set mmu debug
|
||||||
|
|
||||||
|
load test_cu.b6
|
||||||
|
|
||||||
|
;echo Должно быть три останова подряд на адресе 1015.
|
||||||
|
;br 1015
|
||||||
|
go 10
|
||||||
|
go
|
||||||
|
go
|
||||||
|
|
||||||
|
;s 4000000
|
||||||
|
;quit
|
37
BESM6/test_pprog05.b6
Normal file
37
BESM6/test_pprog05.b6
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
;
|
||||||
|
; Пультовая программа #5: тест умножения-деления.
|
||||||
|
; Проверка основных массовых цепей АУ и операций сложения,
|
||||||
|
; умножения, деления на переменном коде.
|
||||||
|
;
|
||||||
|
; Образование переменного кода арифметическим сложением.
|
||||||
|
; Получение нулевого порядка (100000) для увеличения диапазона
|
||||||
|
; используемых чисел.
|
||||||
|
; Умножение на эталон, деление на эталон и вычитание эталона
|
||||||
|
; дают в результате некоторое число с отрицательным порядком,
|
||||||
|
; которое должно быть меньше чем 2**-37 (37-десятичное число).
|
||||||
|
; Увеличение порядка на 37(10) не должно изменить нулевого знака
|
||||||
|
; порядка, если операции умножения и деления выполнены верно;
|
||||||
|
; т.к. операция СЛПА относится к группе умножения, то по нулю
|
||||||
|
; знака порядка операция ПЕ осуществляет передачу управления
|
||||||
|
; на начало теста.
|
||||||
|
;
|
||||||
|
; Переменный код получается в тесте с помощью операции СЛ.
|
||||||
|
; Поэтому, чтобы тест шел достаточно долго, необходимо
|
||||||
|
; на 7 тумблерном регистре набирать не слишком большие
|
||||||
|
; нормализованные числа, не более 2**48
|
||||||
|
; (110000 – порядок числа).
|
||||||
|
;
|
||||||
|
в 1
|
||||||
|
к сл 7, зп 11 ; код := т.рег.7
|
||||||
|
к вчп 11, зп 10 ; в эталон
|
||||||
|
к умн 10, дел 10
|
||||||
|
к вч 10, слпа 145 ; 64+37
|
||||||
|
к пе 6, стоп
|
||||||
|
в 6
|
||||||
|
к сч 11, пб 1 ; если хорошо
|
||||||
|
в 7
|
||||||
|
ч 1.0 ; тумб.регистр 7
|
||||||
|
с 0 ; эталон
|
||||||
|
с 0 ; код
|
||||||
|
|
||||||
|
п 1
|
21
BESM6/test_pprog05.ini
Normal file
21
BESM6/test_pprog05.ini
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
! rm -f log.txt
|
||||||
|
;set console log=log.txt
|
||||||
|
;set console debug=log
|
||||||
|
;set cpu debug
|
||||||
|
|
||||||
|
load test_pprog05.b6
|
||||||
|
ex -ml 1-6
|
||||||
|
ex 7-11
|
||||||
|
echo
|
||||||
|
echo Должно быть четыре останова с числами на сумматоре: 1.0 2.0 3.0 4.0.
|
||||||
|
br 2
|
||||||
|
go
|
||||||
|
ex -f ACC
|
||||||
|
go
|
||||||
|
ex -f ACC
|
||||||
|
go
|
||||||
|
ex -f ACC
|
||||||
|
go
|
||||||
|
ex -f ACC
|
||||||
|
|
||||||
|
quit
|
343
Visual Studio Projects/BESM6.vcproj
Normal file
343
Visual Studio Projects/BESM6.vcproj
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="BESM6"
|
||||||
|
ProjectGUID="{A8D46C10-8F3F-47CA-AD5F-E3BB7C4A3678}"
|
||||||
|
RootNamespace="BESM6"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="131072"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="..\BIN\NT\$(PlatformName)-$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="..\BIN\NT\Project\simh\$(ProjectName)\$(PlatformName)-$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
CharacterSet="0"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
Description="Check for required build dependencies & git commit id"
|
||||||
|
CommandLine="Pre-Build-Event.cmd LIBPCRE"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="./;../;../BESM6/;"../../windows-build/PCRE/include/""
|
||||||
|
PreprocessorDefinitions="USE_INT64;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC"
|
||||||
|
KeepComments="false"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="0"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
CompileAs="1"
|
||||||
|
ShowIncludes="false"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wsock32.lib winmm.lib pcrestaticd.lib pcreposixstaticd.lib"
|
||||||
|
LinkIncremental="2"
|
||||||
|
AdditionalLibraryDirectories="../../windows-build/PCRE/lib/"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
StackReserveSize="10485760"
|
||||||
|
StackCommitSize="10485760"
|
||||||
|
RandomizedBaseAddress="1"
|
||||||
|
DataExecutionPrevention="0"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="..\BIN\NT\$(PlatformName)-$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="..\BIN\NT\Project\simh\$(ProjectName)\$(PlatformName)-$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
CharacterSet="0"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
Description="Check for required build dependencies & git commit id"
|
||||||
|
CommandLine="Pre-Build-Event.cmd LIBPCRE"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
OmitFramePointers="true"
|
||||||
|
AdditionalIncludeDirectories="./;../;../BESM6/;"../../windows-build/PCRE/include/""
|
||||||
|
PreprocessorDefinitions="USE_INT64;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC"
|
||||||
|
StringPooling="true"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
CompileAs="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wsock32.lib winmm.lib pcrestatic.lib pcreposixstatic.lib"
|
||||||
|
LinkIncremental="1"
|
||||||
|
AdditionalLibraryDirectories="../../windows-build/PCRE/lib/"
|
||||||
|
GenerateDebugInformation="false"
|
||||||
|
SubSystem="1"
|
||||||
|
StackReserveSize="10485760"
|
||||||
|
StackCommitSize="10485760"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
RandomizedBaseAddress="1"
|
||||||
|
DataExecutionPrevention="0"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_arith.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_cpu.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_disk.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_drum.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_mmu.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_panel.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_printer.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_punch.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_sys.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_tty.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\scp.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_console.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_disk.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_ether.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_fio.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_serial.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_sock.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_tape.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_timer.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_tmxr.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\BESM6\besm6_defs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\scp.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_console.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_defs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_disk.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_ether.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_fio.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_rev.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_serial.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_sock.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_tape.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_timer.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sim_tmxr.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -113,6 +113,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SAGE", "SAGE.vcproj", "{9D0
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDQ3", "PDQ3.vcproj", "{D4F5761A-B543-40ED-9892-12A0255C2B6D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDQ3", "PDQ3.vcproj", "{D4F5761A-B543-40ED-9892-12A0255C2B6D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BESM6", "BESM6.vcproj", "{A8D46C10-8F3F-47CA-AD5F-E3BB7C4A3678}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
|
@ -283,6 +285,10 @@ Global
|
||||||
{D4F5761A-B543-40ED-9892-12A0255C2B6D}.Debug|Win32.Build.0 = Debug|Win32
|
{D4F5761A-B543-40ED-9892-12A0255C2B6D}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{D4F5761A-B543-40ED-9892-12A0255C2B6D}.Release|Win32.ActiveCfg = Release|Win32
|
{D4F5761A-B543-40ED-9892-12A0255C2B6D}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{D4F5761A-B543-40ED-9892-12A0255C2B6D}.Release|Win32.Build.0 = Release|Win32
|
{D4F5761A-B543-40ED-9892-12A0255C2B6D}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{A8D46C10-8F3F-47CA-AD5F-E3BB7C4A3678}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{A8D46C10-8F3F-47CA-AD5F-E3BB7C4A3678}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{A8D46C10-8F3F-47CA-AD5F-E3BB7C4A3678}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{A8D46C10-8F3F-47CA-AD5F-E3BB7C4A3678}.Release|Win32.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
59
makefile
59
makefile
|
@ -68,6 +68,8 @@ ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS
|
||||||
VIDEO_USEFUL = true
|
VIDEO_USEFUL = true
|
||||||
DISPLAY_USEFUL = true
|
DISPLAY_USEFUL = true
|
||||||
endif
|
endif
|
||||||
|
else ifneq (,$(findstring besm6,$(MAKECMDGOALS)))
|
||||||
|
VIDEO_USEFUL = true
|
||||||
else
|
else
|
||||||
ifeq ($(MAKECMDGOALS),)
|
ifeq ($(MAKECMDGOALS),)
|
||||||
# default target is all
|
# default target is all
|
||||||
|
@ -298,8 +300,8 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
||||||
endif
|
endif
|
||||||
$(info lib paths are: $(LIBPATH))
|
$(info lib paths are: $(LIBPATH))
|
||||||
$(info include paths are: $(INCPATH))
|
$(info include paths are: $(INCPATH))
|
||||||
find_lib = $(strip $(firstword $(foreach dir,$(strip $(LIBPATH)),$(wildcard $(dir)/lib$(1).$(LIBEXT)))))
|
find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip $(LIBPATH)),$(wildcard $(dir)/lib$(1).$(LIBEXT))))))
|
||||||
find_include = $(strip $(firstword $(foreach dir,$(strip $(INCPATH)),$(wildcard $(dir)/$(1).h))))
|
find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip $(INCPATH)),$(wildcard $(dir)/$(1).h)))))
|
||||||
need_search = $(strip $(shell ld -l$(1) /dev/null 2>&1 | grep $(1) | sed s/$(1)//))
|
need_search = $(strip $(shell ld -l$(1) /dev/null 2>&1 | grep $(1) | sed s/$(1)//))
|
||||||
LD_SEARCH_NEEDED := $(call need_search,ZzzzzzzZ)
|
LD_SEARCH_NEEDED := $(call need_search,ZzzzzzzZ)
|
||||||
ifneq (,$(call find_lib,m))
|
ifneq (,$(call find_lib,m))
|
||||||
|
@ -1159,6 +1161,53 @@ SSEMD = SSEM
|
||||||
SSEM = ${SSEMD}/ssem_cpu.c ${SSEMD}/ssem_sys.c
|
SSEM = ${SSEMD}/ssem_cpu.c ${SSEMD}/ssem_sys.c
|
||||||
SSEM_OPT = -I ${SSEMD}
|
SSEM_OPT = -I ${SSEMD}
|
||||||
|
|
||||||
|
###
|
||||||
|
### Experimental simulators
|
||||||
|
###
|
||||||
|
|
||||||
|
BESM6D = BESM6
|
||||||
|
BESM6 = ${BESM6D}/besm6_cpu.c ${BESM6D}/besm6_sys.c ${BESM6D}/besm6_mmu.c \
|
||||||
|
${BESM6D}/besm6_arith.c ${BESM6D}/besm6_disk.c ${BESM6D}/besm6_drum.c \
|
||||||
|
${BESM6D}/besm6_tty.c ${BESM6D}/besm6_panel.c ${BESM6D}/besm6_printer.c \
|
||||||
|
${BESM6D}/besm6_punch.c
|
||||||
|
|
||||||
|
ifneq (,${VIDEO_LDFLAGS})
|
||||||
|
ifeq (,${FONTFILE})
|
||||||
|
FONTPATH += /usr/share/fonts /Library/Fonts /usr/lib/jvm /System/Library/Frameworks/JavaVM.framework/Versions
|
||||||
|
FONTPATH := $(dir $(foreach dir,$(strip $(FONTPATH)),$(wildcard $(dir)/.)))
|
||||||
|
FONTNAME += DejaVuSans.ttf LucidaSansRegular.ttf FreeSans.ttf AppleGothic.ttf
|
||||||
|
$(info font paths are: $(FONTPATH))
|
||||||
|
$(info font names are: $(FONTNAME))
|
||||||
|
find_fontfile = $(strip $(firstword $(foreach dir,$(strip $(FONTPATH)),$(wildcard $(dir)/$(1))$(wildcard $(dir)/*/$(1))$(wildcard $(dir)/*/*/$(1))$(wildcard $(dir)/*/*/*/$(1)))))
|
||||||
|
find_font = $(abspath $(strip $(firstword $(foreach font,$(strip $(FONTNAME)),$(call find_fontfile,$(font))))))
|
||||||
|
ifneq (,$(call find_font))
|
||||||
|
FONTFILE=$(call find_font)
|
||||||
|
else
|
||||||
|
$(info ***)
|
||||||
|
$(info *** No font file available, BESM-6 video panel disabled.)
|
||||||
|
$(info ***)
|
||||||
|
$(info *** To enable the panel display please specify one of:)
|
||||||
|
$(info *** a font path with FONTNAME=path)
|
||||||
|
$(info *** a font name with FONTNAME=fontname.ttf)
|
||||||
|
$(info *** a font file with FONTFILE=path/fontname.ttf)
|
||||||
|
$(info ***)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifeq (,$(and ${VIDEO_LDFLAGS}, ${FONTFILE}))
|
||||||
|
BESM6_OPT = -I ${BESM6D} -DUSE_INT64
|
||||||
|
else ifneq (,$(and $(findstring SDL2,${VIDEO_LDFLAGS}),$(call find_include,SDL2/SDL_ttf),$(call find_lib,SDL2_ttf)))
|
||||||
|
$(info using libSDL2_ttf: $(call find_lib,SDL2_ttf) $(call find_include,SDL2/SDL_ttf))
|
||||||
|
$(info ***)
|
||||||
|
BESM6_OPT = -I ${BESM6D} -DFONTFILE=${FONTFILE} -DUSE_INT64 ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL2_ttf
|
||||||
|
else ifneq (,$(and $(call find_include,SDL/SDL_ttf),$(call find_lib,SDL_ttf)))
|
||||||
|
$(info using libSDL_ttf: $(call find_lib,SDL_ttf) $(call find_include,SDL/SDL_ttf))
|
||||||
|
$(info ***)
|
||||||
|
BESM6_OPT = -I ${BESM6D} -DFONTFILE=${FONTFILE} -DUSE_INT64 ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL_ttf
|
||||||
|
else
|
||||||
|
BESM6_OPT = -I ${BESM6D} -DUSE_INT64
|
||||||
|
endif
|
||||||
|
|
||||||
###
|
###
|
||||||
### Unsupported/Incomplete simulators
|
### Unsupported/Incomplete simulators
|
||||||
###
|
###
|
||||||
|
@ -1462,6 +1511,12 @@ ${BIN}ssem${EXE} : ${SSEM} ${SIM}
|
||||||
${MKDIRBIN}
|
${MKDIRBIN}
|
||||||
${CC} ${SSEM} ${SIM} ${SSEM_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
${CC} ${SSEM} ${SIM} ${SSEM_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
||||||
|
|
||||||
|
besm6 : ${BIN}besm6${EXE}
|
||||||
|
|
||||||
|
${BIN}besm6${EXE} : ${BESM6} ${SIM}
|
||||||
|
${MKDIRBIN}
|
||||||
|
${CC} ${BESM6} ${SIM} ${BESM6_OPT} $(CC_OUTSPEC) ${LDFLAGS}
|
||||||
|
|
||||||
sigma : ${BIN}sigma${EXE}
|
sigma : ${BIN}sigma${EXE}
|
||||||
|
|
||||||
${BIN}sigma${EXE} : ${SIGMA} ${SIM}
|
${BIN}sigma${EXE} : ${SIGMA} ${SIM}
|
||||||
|
|
Loading…
Add table
Reference in a new issue