BESM6: Converted files to CRLF format

Also added support for loading such files, and a few tests.
This commit is contained in:
Leo Broukhis 2014-12-30 00:41:31 -08:00
parent 659600ff59
commit b4eeaa77de
20 changed files with 10891 additions and 7730 deletions

View file

@ -1,483 +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 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;
}
}
}
/*
* 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 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;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,426 +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 <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 10 /* одна микросекунда - десять тактов */
#define MSEC (1000*USEC) /* одна миллисекунда */
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern int32 sim_interval, sim_step;
extern FILE *sim_deb, *sim_log;
extern int32 sim_switches;
extern UNIT cpu_unit;
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);
int printer_is_idle (void);
/*
* Терминалы (телетайпы, видеотоны, "Консулы").
*/
void tty_send (uint32 mask);
int tty_query (void);
void vt_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);
int fs_is_idle (void);
/*
* Отладочная выдача.
*/
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_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
/*
* 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 <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 10 /* одна микросекунда - десять тактов */
#define MSEC (1000*USEC) /* одна миллисекунда */
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern int32 sim_interval, sim_step;
extern FILE *sim_deb, *sim_log;
extern int32 sim_switches;
extern UNIT cpu_unit;
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);
int printer_is_idle (void);
/*
* Терминалы (телетайпы, видеотоны, "Консулы").
*/
void tty_send (uint32 mask);
int tty_query (void);
void vt_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);
int fs_is_idle (void);
/*
* Отладочная выдача.
*/
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_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

File diff suppressed because it is too large Load diff

View file

@ -1,372 +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;
}
/*
* 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;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,345 +1,345 @@
/*
* 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];
int acpu_isatty[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;
acpu_isatty[num] = !strcmp(cptr, "/dev/tty");
if (!acpu_isatty[num]) {
/* Write UTF-8 tag: zero width no-break space. */
fputs ("\xEF\xBB\xBF", u->fileref);
}
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;
switch (dev->curchar) {
case 0 ... 0137:
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;
}
break;
case 0140:
/* 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);
break;
}
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);
}
}
if (acpu_isatty[num])
fputc('\r', fout);
fputc ('\n', fout);
memset(dev->line, 0, sizeof (dev->line));
dev->length = dev->strikes = 0;
}
/*
* Выясняем, остановлены ли АЦПУ. Нужно для входа в "спящий" режим.
*/
int printer_is_idle ()
{
if ((printer_unit[0].flags & UNIT_ATT) && acpu[0].rampup == 0)
return 0;
if ((printer_unit[1].flags & UNIT_ATT) && acpu[1].rampup == 0)
return 0;
return 1;
}
/*
* 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];
int acpu_isatty[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;
acpu_isatty[num] = !strcmp(cptr, "/dev/tty");
if (!acpu_isatty[num]) {
/* Write UTF-8 tag: zero width no-break space. */
fputs ("\xEF\xBB\xBF", u->fileref);
}
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;
switch (dev->curchar) {
case 0 ... 0137:
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;
}
break;
case 0140:
/* 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);
break;
}
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);
}
}
if (acpu_isatty[num])
fputc('\r', fout);
fputc ('\n', fout);
memset(dev->line, 0, sizeof (dev->line));
dev->length = dev->strikes = 0;
}
/*
* Выясняем, остановлены ли АЦПУ. Нужно для входа в "спящий" режим.
*/
int printer_is_idle ()
{
if ((printer_unit[0].flags & UNIT_ATT) && acpu[0].rampup == 0)
return 0;
if ((printer_unit[1].flags & UNIT_ATT) && acpu[1].rampup == 0)
return 0;
return 1;
}

View file

@ -1,472 +1,472 @@
/*
* 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"
#include <sys/stat.h>
#include <sys/fcntl.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;
struct stat stbuf;
fstat (fileno(u->fileref), &stbuf);
isfifo[num] = (stbuf.st_mode & S_IFIFO) != 0;
if (isfifo[num]) {
int flags = fcntl(fileno(u->fileref), F_GETFL, 0);
fcntl(fileno(u->fileref), F_SETFL, flags | O_NONBLOCK);
}
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:
switch (fs_state[num]) {
case FS_STARTING:
/* По первому прерыванию после запуска двигателя ничего не читаем */
FS[num] = 0;
fs_state[num] = FS_RUNNING;
break;
case 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;
}
break;
}
case FS_IMAGE ... 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];
}
break;
}
case 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;
break;
}
case FS_FILLUP ... FS_FILLUP_LAST:
FS[num] = 0;
if (++fs_state[num] == FS_ENDA3) {
fs_state[num] = FS_IMAGE;
}
break;
case FS_ENDA3 ... 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;
}
break;
case FS_IDLE:
case FS_TAIL:
FS[num] = 0;
break;
}
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];
}
int fs_is_idle (void)
{
return fs_state[0] == FS_IDLE && fs_state[1] == FS_IDLE;
}
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);
}
/*
* 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"
#include <sys/stat.h>
#include <sys/fcntl.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;
struct stat stbuf;
fstat (fileno(u->fileref), &stbuf);
isfifo[num] = (stbuf.st_mode & S_IFIFO) != 0;
if (isfifo[num]) {
int flags = fcntl(fileno(u->fileref), F_GETFL, 0);
fcntl(fileno(u->fileref), F_SETFL, flags | O_NONBLOCK);
}
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:
switch (fs_state[num]) {
case FS_STARTING:
/* По первому прерыванию после запуска двигателя ничего не читаем */
FS[num] = 0;
fs_state[num] = FS_RUNNING;
break;
case 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;
}
break;
}
case FS_IMAGE ... 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];
}
break;
}
case 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;
break;
}
case FS_FILLUP ... FS_FILLUP_LAST:
FS[num] = 0;
if (++fs_state[num] == FS_ENDA3) {
fs_state[num] = FS_IMAGE;
}
break;
case FS_ENDA3 ... 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;
}
break;
case FS_IDLE:
case FS_TAIL:
FS[num] = 0;
break;
}
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];
}
int fs_is_idle (void)
{
return fs_state[0] == FS_IDLE && fs_state[1] == FS_IDLE;
}
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);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

484
BESM6/boot_dispak.b6 Normal file
View 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

92
BESM6/dispak.ini Normal file
View file

@ -0,0 +1,92 @@
! rm -f log.txt
set console log=log.txt
set console debug=log
;set cpu debug
;set mmu debug
;set drum debug
;set disk debug
;
; Приводим барабаны в исходное состояние.
;
! rm -f drum1x.bin drum2x.bin
attach drum0 drum1x.bin
attach drum1 drum2x.bin
;
; Создаем рабочий диск.
;
! ./formatdisk 2052 > 2052.bin
;
; Подключаем диски.
;
attach -e disk7 sbor2053.bin
attach -e disk6 2052.bin
attach -e disk5 krab2063.bin
attach -e disk0 sbor2048.bin
attach -e disk1 svs2048.bin
attach -e disk2 alt2048.bin
;
; Подключаем АЦПУ.
;
attach prn0 /dev/tty
;
; Активируем операторский терминал,
; на который идут сообщения.
;
attach tty1 /dev/tty
;
; Режимы по вкусу
;
;set tty1 jcuken,authbs
set tty1 authbs
set 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

63
BESM6/formatdisk.c Executable file
View file

@ -0,0 +1,63 @@
/*
* formatdisk.c - A utility to produce blank BESM-6 disk images.
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "besm6_defs.h"
#define TOTBLK 01767
int main(int argc, char ** argv) {
t_value control[4]; /* block (zone) number, key, userid, checksum */
int diskno, blkno, word;
if (argc != 2 || (diskno = atoi(argv[1])) < 2048 || diskno > 4095) {
fprintf(stderr, "Usage: formatdisk NNNN > diskNNNN.bin, where 2048 <= NNNN <= 4095\n");
exit(1);
}
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 */
control[1] |= diskno << 12;
for (blkno = 0; blkno < TOTBLK; ++blkno) {
control[0] = SET_CONVOL((t_value)(2*blkno) << 36, CONVOL_NUMBER);
fwrite(control, sizeof(t_value), 4, stdout);
control[0] = SET_CONVOL((t_value)(2*blkno+1) << 36, CONVOL_NUMBER);
fwrite(control, sizeof(t_value), 4, stdout);
for (word = 0; word < 02000; ++word) {
fwrite(control+2, sizeof(t_value), 1, stdout);
}
}
exit(0);
}

2425
BESM6/test_alu.b6 Normal file

File diff suppressed because it is too large Load diff

16
BESM6/test_alu.ini Normal file
View 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
View 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
View 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

22
BESM6/test_pprog05.ini Normal file
View file

@ -0,0 +1,22 @@
! 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
go
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

View file

@ -1170,15 +1170,17 @@ 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
ifeq (,${VIDEO_LDFLAGS})
BESM6_OPT = -I ${BESM6D} -DUSE_INT64
else ifneq (,$(and $(findstring,SDL2,${VIDEO_LDFLAGS})),$(and($(find_include, SDL2/SDL_ttf),$(find_lib,SDL2_ttf))))
FORMATDISK = ${BESM6D}/formatdisk.c
ifeq (,${VIDEO_LDFLAGS})
BESM6_OPT = -I ${BESM6D} -DUSE_INT64
else ifneq (,$(and $(findstring,SDL2,${VIDEO_LDFLAGS})),$(and($(find_include, SDL2/SDL_ttf),$(find_lib,SDL2_ttf))))
BESM6_OPT = -I ${BESM6D} -DUSE_INT64 ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL2_ttf
else ifneq (,$(and $(find_include, SDL/SDL_ttf),$(find_lib,SDL_ttf)))
else ifneq (,$(and $(find_include, SDL/SDL_ttf),$(find_lib,SDL_ttf)))
BESM6_OPT = -I ${BESM6D} -DUSE_INT64 ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL_ttf
endif
endif
###
### Unsupported/Incomplete simulators
###
@ -1482,12 +1484,16 @@ ${BIN}ssem${EXE} : ${SSEM} ${SIM}
${MKDIRBIN}
${CC} ${SSEM} ${SIM} ${SSEM_OPT} $(CC_OUTSPEC) ${LDFLAGS}
besm6 : ${BIN}besm6${EXE}
besm6 : ${BIN}besm6${EXE} ${BIN}formatdisk${EXE}
${BIN}besm6${EXE} : ${BESM6} ${SIM}
${MKDIRBIN}
${CC} ${BESM6} ${SIM} ${BESM6_OPT} $(CC_OUTSPEC) ${LDFLAGS}
${BIN}formatdisk${EXE} : ${FORMATDISK}
${MKDIRBIN}
${CC} ${FORMATDISK} ${BESM6_OPT} $(CC_OUTSPEC)
sigma : ${BIN}sigma${EXE}
${BIN}sigma${EXE} : ${SIGMA} ${SIM}