mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 23:35:30 +00:00
ICL1900: Added support for standard I/O and console device.
This commit is contained in:
parent
5439436f21
commit
a809a48b56
@ -1087,7 +1087,8 @@ DISPLAYD = display
|
||||
# Emulator source files and compile time options
|
||||
#
|
||||
ICL1900D = ./
|
||||
ICL1900 = ${ICL1900D}icl1900_cpu.c ${ICL1900D}icl1900_sys.c
|
||||
ICL1900 = ${ICL1900D}icl1900_cpu.c ${ICL1900D}icl1900_sys.c ${ICL1900D}icl1900_stdio.c \
|
||||
${ICL1900D}icl1900_cty.c
|
||||
ICL1900_OPT = -I.. -DUSE_SIM_CARD
|
||||
|
||||
#
|
||||
|
||||
36
ICL1900/div.c
Normal file
36
ICL1900/div.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define N 24
|
||||
#define B0 (1<<N)
|
||||
#define B1 (1<<(N-1))
|
||||
#define M0 ((1<<(N))-1)
|
||||
main(int argc, char *argv[]) {
|
||||
int n = N;
|
||||
int a = 0;
|
||||
int m = atoi(argv[2]);
|
||||
int q = atoi(argv[1]);
|
||||
|
||||
printf("0: n=%d B0=%08o B1=%08o M0=%08o\n", n, B0, B1, M0);
|
||||
do {
|
||||
a <<= 1;
|
||||
q <<= 1;
|
||||
if (q & B0)
|
||||
a |= 1;
|
||||
if (a & B0) {
|
||||
a = a+m;
|
||||
} else {
|
||||
a = a + (m^ M0) + 1;
|
||||
}
|
||||
a &= M0;
|
||||
q &= M0;
|
||||
if ((a& B1) == 0)
|
||||
q|= 1;
|
||||
printf("1: n=%d m=%08o a=%08o q=%08o\n", n, m, a, q);
|
||||
n--;
|
||||
} while (n != 0);
|
||||
if (a & B1)
|
||||
a = a+m;
|
||||
printf("2: n=%d m=%08o a=%08o q=%08o\n", n, m, a, q);
|
||||
}
|
||||
|
||||
@ -105,12 +105,9 @@ uint8 RF; /* Function code */
|
||||
uint32 RL; /* Limit register */
|
||||
uint8 RG; /* General register */
|
||||
uint32 RM; /* M field register */
|
||||
uint32 RN; /* Current address */
|
||||
uint32 RP; /* Temp register */
|
||||
uint32 RS; /* Temp register */
|
||||
uint32 RT; /* Temp register */
|
||||
uint32 MB; /* Memory buffer */
|
||||
uint32 MA; /* Memory address */
|
||||
uint8 RX; /* X field register */
|
||||
uint32 XR[8]; /* Index registers */
|
||||
uint32 faccl; /* Floating point accumulator low */
|
||||
@ -175,6 +172,8 @@ t_stat cpu_help(FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||
t_stat rtc_srv(UNIT * uptr);
|
||||
|
||||
int32 rtc_tps = 60 ;
|
||||
int32 tmxr_poll = 10000;
|
||||
|
||||
|
||||
|
||||
/* CPU data structures
|
||||
@ -323,13 +322,11 @@ t_stat
|
||||
sim_instr(void)
|
||||
{
|
||||
t_stat reason;
|
||||
uint32 temp;
|
||||
uint32 temp2;
|
||||
int x_reg;
|
||||
int m;
|
||||
int n;
|
||||
uint32 temp; /* Hol order code being obeyed */
|
||||
int m; /* Holds index register for address modification */
|
||||
int n; /* Generic short term temp register */
|
||||
int e1,e2; /* Temp for exponents */
|
||||
int f;
|
||||
int f; /* Used to hold flags */
|
||||
|
||||
reason = 0;
|
||||
adrmask = (Mode & AM22) ? M22 : M15;
|
||||
@ -513,7 +510,7 @@ obey:
|
||||
RB = RB ^ FMASK;
|
||||
BCarry = !BCarry;
|
||||
}
|
||||
temp2 = (RA & B0) != 0;
|
||||
n = (RA & B0) != 0;
|
||||
RA = RA + RB + BCarry;
|
||||
if (RF & 04) {
|
||||
if (RF & 02)
|
||||
@ -524,7 +521,7 @@ obey:
|
||||
} else {
|
||||
int t2 = (RB & B0) != 0;
|
||||
int tr = (RA & B0) != 0;
|
||||
if ((temp2 && t2 && !tr) || (!temp2 && !t2 && tr))
|
||||
if ((n && t2 && !tr) || (!n && !t2 && tr))
|
||||
BV = 1;
|
||||
BCarry = 0;
|
||||
}
|
||||
@ -609,9 +606,13 @@ obey:
|
||||
break;
|
||||
|
||||
case OP_STOZ: /* Store Zero */
|
||||
RA = 0;
|
||||
#if 0 /* Stevenage Machines */
|
||||
if (exe_mode)
|
||||
XR[RX] = RA;
|
||||
#endif
|
||||
RB = 0;
|
||||
BCarry = 0;
|
||||
if (Mem_write(RS, &RA, 1)) {
|
||||
if (Mem_write(RS, &RB, 1)) {
|
||||
goto intr;
|
||||
}
|
||||
break;
|
||||
@ -664,15 +665,15 @@ obey:
|
||||
}
|
||||
RP = RA;
|
||||
RA = RB;
|
||||
temp2 = RP & 1;
|
||||
n = RP & 1;
|
||||
RP >>= 1;
|
||||
if (RF & 1) /* Multiply and Round */
|
||||
RP |= B0;
|
||||
RB = 0;
|
||||
for(RK = 23; RK != 0; RK--) {
|
||||
if (temp2)
|
||||
if (n)
|
||||
RB += RA;
|
||||
temp2 = RP & 1;
|
||||
n = RP & 1;
|
||||
RP >>= 1;
|
||||
if (RB & 1)
|
||||
RP |= B0;
|
||||
@ -681,11 +682,11 @@ obey:
|
||||
RB >>= 1;
|
||||
}
|
||||
|
||||
if (temp2) {
|
||||
if (n) {
|
||||
RB += (RA ^ FMASK) + 1;
|
||||
}
|
||||
temp2 = RP & 1; /* Check for MPR */
|
||||
if (temp2 && RP & B0)
|
||||
n = RP & 1; /* Check for MPR */
|
||||
if (n && RP & B0)
|
||||
RB++;
|
||||
RP >>= 1;
|
||||
if (RF == OP_MPA) {
|
||||
@ -765,7 +766,7 @@ obey:
|
||||
RB = XR[RX]; /* Dividend to RB/RP */
|
||||
f =0;
|
||||
//fprintf(stderr, "DVD: %08o %08o %08o - %3o C=%08o\n\r", RA, RP, RB, RF, RC);
|
||||
if (RA == FMASK && RP == 1 && RB == 0)
|
||||
if (RA == FMASK && RP == 1 && RB == 0) /* Flag special case */
|
||||
f=1;
|
||||
|
||||
if (RA == 0) { /* Exit on zero divisor */ /* VI */
|
||||
@ -774,7 +775,7 @@ obey:
|
||||
break;
|
||||
}
|
||||
BCarry = (RP & B0) != 0;
|
||||
temp = (RP | RB) == 0; /* Save zero dividend */
|
||||
n = (RP | RB) == 0; /* Save zero dividend */
|
||||
|
||||
/* Setup for specific divide order code */ /* V11 */
|
||||
if (RF & 2) { /* DVS */
|
||||
@ -791,20 +792,20 @@ obey:
|
||||
|
||||
/* First partial remainder */ /* V12 */
|
||||
if (((RB ^ RA) & B0) == 0) {
|
||||
temp2 = RB + (RA ^ FMASK) + 1;
|
||||
RS = RB + (RA ^ FMASK) + 1;
|
||||
RK=1;
|
||||
} else {
|
||||
temp2 = RB + RA;
|
||||
RS = RB + RA;
|
||||
RK=0;
|
||||
}
|
||||
if (((temp2 ^ RA) & B0) != 0)
|
||||
if (((RS ^ RA) & B0) != 0)
|
||||
BCarry = 1;
|
||||
BCarry = RK != BCarry;
|
||||
RP <<= 1;
|
||||
if (((temp2 ^ RA) & B0) == 0) {
|
||||
if (((RS ^ RA) & B0) == 0) {
|
||||
RP |= 1;
|
||||
}
|
||||
RB = temp2 << 1;
|
||||
RB = RS << 1;
|
||||
if (RP & BM1)
|
||||
RB |= 1;
|
||||
RB &= FMASK;
|
||||
@ -813,16 +814,16 @@ obey:
|
||||
|
||||
/* Main divide loop */ /* V13 */
|
||||
for (RK = 22; RK != 0; RK--) {
|
||||
if (((temp2 ^ RA) & B0) == 0) {
|
||||
temp2 = RB + (RA ^ FMASK) + 1;
|
||||
if (((RS ^ RA) & B0) == 0) {
|
||||
RS = RB + (RA ^ FMASK) + 1;
|
||||
} else {
|
||||
temp2 = RB + RA;
|
||||
RS = RB + RA;
|
||||
}
|
||||
RP <<= 1;
|
||||
if (((temp2 ^ RA) & B0) == 0) {
|
||||
if (((RS ^ RA) & B0) == 0) {
|
||||
RP |= 1;
|
||||
}
|
||||
RB = temp2 << 1;
|
||||
RB = RS << 1;
|
||||
if (RP & BM1)
|
||||
RB |= 1;
|
||||
RB &= FMASK;
|
||||
@ -831,13 +832,13 @@ obey:
|
||||
}
|
||||
|
||||
/* Final product */
|
||||
if (((temp2 ^ RA) & B0) == 0) { /* V14 */
|
||||
temp2 = RB + (RA ^ FMASK) + 1;
|
||||
if (((RS ^ RA) & B0) == 0) { /* V14 */
|
||||
RS = RB + (RA ^ FMASK) + 1;
|
||||
} else {
|
||||
temp2 = RB + RA;
|
||||
RS = RB + RA;
|
||||
}
|
||||
RP <<= 1;
|
||||
if (((temp2 ^ RA) & B0) == 0) {
|
||||
if (((RS ^ RA) & B0) == 0) {
|
||||
RP |= 1;
|
||||
}
|
||||
RP &= FMASK;
|
||||
@ -856,9 +857,9 @@ obey:
|
||||
//fprintf(stderr, "DVD5: %08o %08o %08o \n\r", RA, RP, RB);
|
||||
/* Form final partial product */
|
||||
if (RA & B0) {
|
||||
temp2 = (RB + (RA ^ FMASK) + 1) & FMASK;
|
||||
RS = (RB + (RA ^ FMASK) + 1) & FMASK;
|
||||
//fprintf(stderr, "DVD5: %08o %08o %08o %08o\n\r", RA, RP, RB, RT);
|
||||
if (temp2 == 0) {
|
||||
if (RS == 0) {
|
||||
RB = 0;
|
||||
goto dvd1;
|
||||
}
|
||||
@ -883,7 +884,7 @@ dvd1:
|
||||
BCarry = 1;
|
||||
dvd2:
|
||||
//fprintf(stderr, "DVD7: %08o %08o %08o \n\r", RA, RP, RB);
|
||||
if (temp)
|
||||
if (n)
|
||||
BCarry = 0;
|
||||
if (BCarry)
|
||||
BV = 1;
|
||||
@ -1130,15 +1131,15 @@ branch:
|
||||
RK = RB & 01777;
|
||||
BCarry = 0;
|
||||
while (RK != 0) {
|
||||
temp2 = 0;
|
||||
n = 0;
|
||||
switch (m) {
|
||||
case 0: temp2 = (RA & B0) != 0; break;
|
||||
case 0: n = (RA & B0) != 0; break;
|
||||
case 1: break;
|
||||
case 2:
|
||||
case 3: temp = RA & B0;
|
||||
}
|
||||
RA <<= 1;
|
||||
RA |= temp2;
|
||||
RA |= n;
|
||||
if ((m & 2) && temp != (RA & B0))
|
||||
BV = 1;
|
||||
RA &= FMASK;
|
||||
@ -1175,9 +1176,9 @@ branch:
|
||||
if (RB & B0)
|
||||
RA |= 1;
|
||||
RB &= M23;
|
||||
temp2 = (RA & B0) != 0;
|
||||
n = (RA & B0) != 0;
|
||||
temp = (RA & BM1) != 0;
|
||||
if (temp2 != temp)
|
||||
if (n != temp)
|
||||
BV = 1;
|
||||
}
|
||||
RA &= FMASK;
|
||||
@ -1191,23 +1192,23 @@ branch:
|
||||
case OP_SRL: /* Shift Right */
|
||||
m = (RB >> 10) & 03;
|
||||
RK = RB & 01777;
|
||||
temp2 = RA & B0;
|
||||
RT = RA & B0;
|
||||
BCarry = 0;
|
||||
switch(m) {
|
||||
case 0: break;
|
||||
case 1: temp2 = 0; break;
|
||||
case 1: RT = 0; break;
|
||||
case 2: break;
|
||||
case 3: if (BV) {
|
||||
temp2 = B0 ^ temp2;
|
||||
RT = B0 ^ RT;
|
||||
BV = 0;
|
||||
}
|
||||
}
|
||||
while (RK != 0) {
|
||||
if (m == 0)
|
||||
temp2 = (RA & 1) ? B0 : 0;
|
||||
RT = (RA & 1) ? B0 : 0;
|
||||
temp = RA & 1;
|
||||
RA >>= 1;
|
||||
RA |= temp2;
|
||||
RA |= RT;
|
||||
RK--;
|
||||
}
|
||||
if (m > 1 && temp == 1)
|
||||
@ -1220,9 +1221,9 @@ branch:
|
||||
RK = RB & 01777;
|
||||
RB = XR[(RX+1) & 07];
|
||||
BCarry = 0;
|
||||
temp2 = RA & B0;
|
||||
RT = RA & B0;
|
||||
if (m == 3 && RK != 0 && BV) {
|
||||
temp2 = B0^temp2;
|
||||
RT = B0^RT;
|
||||
BV = 0;
|
||||
}
|
||||
while (RK != 0) {
|
||||
@ -1247,7 +1248,7 @@ branch:
|
||||
if (RA & 1)
|
||||
RB |= B1;
|
||||
RA >>= 1;
|
||||
RA |= temp2;
|
||||
RA |= RT;
|
||||
}
|
||||
RK--;
|
||||
}
|
||||
@ -1268,12 +1269,12 @@ branch:
|
||||
RA = RB = 0;
|
||||
} else if (BV) {
|
||||
RT++;
|
||||
temp2 = (RA & B0) ^ B0;
|
||||
RP = (RA & B0) ^ B0;
|
||||
if (RA & 1 && RF & 1)
|
||||
RB |= B0;
|
||||
RB >>= 1;
|
||||
RA >>= 1;
|
||||
RA |= temp2;
|
||||
RA |= RP;
|
||||
} else if (RA != 0 || RB != 0) {
|
||||
/* Shift left until sign and B1 not same */
|
||||
while ((((RA >> 1) ^ RA) & B1) == 0) {
|
||||
@ -1297,8 +1298,7 @@ branch:
|
||||
RB += 0400;
|
||||
if (RB & B0) {
|
||||
RB = RP;
|
||||
temp2 = (RA & M23) +1;
|
||||
if (temp2 & B0)
|
||||
if (((RA & M23) + 1) & B0)
|
||||
RA = RB = 0;
|
||||
}
|
||||
RB = (RB & MMASK) | (RT & M9);
|
||||
@ -1363,6 +1363,17 @@ branch:
|
||||
break;
|
||||
|
||||
case OP_MODE: /* Set Mode */
|
||||
#if 0 /* Stevenage Machines */
|
||||
if (exe_mode && RX == 1)
|
||||
temp = RB; /* Set interrupt enable mode */
|
||||
else
|
||||
/* On Stevenage Machines 002 -> 020 Add Datum */
|
||||
/* On Stevenage Machines 004 -> 000 unused */
|
||||
/* On Stevenage Machines 010 -> 000 unused */
|
||||
/* On Stevenage Machines 020 -> Extended store mode */
|
||||
/* On Stevenage Machines 040 -> 000 unused */
|
||||
/* On Stevenage Machines 0100 -> Carry */
|
||||
#endif
|
||||
if (exe_mode)
|
||||
Mode = RB & 077;
|
||||
else
|
||||
@ -1530,24 +1541,27 @@ branch:
|
||||
}
|
||||
//fprintf(stderr, "FAD5: %08o %08o %08o %08o %08o\n\r", RA, RB, RC, faccl, facch);
|
||||
/* Add the numbers */
|
||||
temp2 = (faccl & B0) != 0; /* Save signs */
|
||||
n = (faccl & B0) != 0; /* Save signs */
|
||||
if (RA & B0)
|
||||
temp2 |= 2;
|
||||
n |= 2;
|
||||
faccl += RA;
|
||||
facch += RB;
|
||||
if (facch & B0) {
|
||||
facch &= M23;
|
||||
faccl ++;
|
||||
}
|
||||
temp = (faccl & B0) != 0;
|
||||
/* Sign of result */
|
||||
if ((faccl & B0) != 0)
|
||||
n |= 4;
|
||||
//fprintf(stderr, "FAD6: %08o %08o %08o %d %d\n\r", faccl, facch, RC, temp, temp2);
|
||||
if ((temp2 == 3 && temp == 0) || (temp2 == 0 && temp != 0)) {
|
||||
/* Result sign not equal same sign as addens */
|
||||
if (n == 3 || n == 4) {
|
||||
if (faccl & 1)
|
||||
facch |= B0;
|
||||
faccl >>= 1;
|
||||
facch >>= 1;
|
||||
facch &= MMASK;
|
||||
if (!temp)
|
||||
if ((n & 4) == 0)
|
||||
faccl |= B0; /* Set sign */
|
||||
e1++;
|
||||
//fprintf(stderr, "FAD6a: %08o %08o %08o %d %d\n\r", faccl, facch, RC, temp, temp2);
|
||||
@ -1579,7 +1593,7 @@ fn:
|
||||
faccl ++;
|
||||
facch &= M23;
|
||||
faccl &= FMASK;
|
||||
temp2 = (faccl & B0) != 0;
|
||||
// temp2 = (faccl & B0) != 0;
|
||||
/* renormalize if things changed */
|
||||
if ((RX & 2) == 0 && (((faccl >> 1) ^ faccl) & B1) == 0) {
|
||||
e1--;
|
||||
@ -1665,35 +1679,35 @@ fexp:
|
||||
}
|
||||
}
|
||||
//fprintf(stderr, "FMP2: %08o %08o %08o %08o %08o %03o %d %o\n\r", RA, RB, RC, faccl, facch, e1, e1, f);
|
||||
temp = faccl;
|
||||
temp2 = facch;
|
||||
RT = faccl;
|
||||
RP = facch;
|
||||
faccl = facch = 0; /* Clear product */
|
||||
/* Do actual multiply */
|
||||
|
||||
for(RK = 37; RK != 0; RK--) {
|
||||
/* If High order bit one, add in RB,RA */
|
||||
if (temp2 & B15) {
|
||||
if (RP & B15) {
|
||||
facch += RB;
|
||||
faccl += RA;
|
||||
if (facch & B0)
|
||||
faccl++;
|
||||
facch &= M23;
|
||||
}
|
||||
/* Shift faccl,fach,temp,t right one */
|
||||
if (temp & 1)
|
||||
temp2 |= B0;
|
||||
/* Shift faccl,fach,RT,t right one */
|
||||
if (RT & 1)
|
||||
RP |= B0;
|
||||
if (facch & 1)
|
||||
temp |= B0;
|
||||
RT |= B0;
|
||||
if (faccl & 1)
|
||||
facch |= B0;
|
||||
temp2 >>= 1;
|
||||
temp >>= 1;
|
||||
RP >>= 1;
|
||||
RT >>= 1;
|
||||
facch >>= 1;
|
||||
faccl >>= 1;
|
||||
//fprintf(stderr, "FMP3: %08o %08o %08o %08o %08o %08o %08o %02o\n\r", RA, RB, RC, faccl, facch, temp, temp2, RK);
|
||||
//fprintf(stderr, "FMP3: %08o %08o %08o %08o %08o %08o %08o %02o\n\r", RA, RB, RC, faccl, facch, RT, RP, RK);
|
||||
}
|
||||
/* Check if still negative multiplican */
|
||||
if (temp2 & B15) {
|
||||
if (RP & B15) {
|
||||
facch += RB;
|
||||
faccl += RA;
|
||||
if (facch & B0)
|
||||
@ -1705,20 +1719,20 @@ fexp:
|
||||
if ((RX & 2) == 0 && faccl == 0 && facch != 0) {
|
||||
while ((faccl & B1) == 0) {
|
||||
e1--;
|
||||
temp2 <<= 1;
|
||||
temp <<= 1;
|
||||
RP <<= 1;
|
||||
RT <<= 1;
|
||||
facch <<= 1;
|
||||
faccl <<= 1;
|
||||
if (temp2 & B0)
|
||||
temp |= 1;
|
||||
if (temp & B0)
|
||||
if (RP & B0)
|
||||
RT |= 1;
|
||||
if (RT & B0)
|
||||
facch |= 1;
|
||||
if (facch & B0)
|
||||
faccl |= 1;
|
||||
faccl &= FMASK;
|
||||
facch &= M23;
|
||||
temp &= M23;
|
||||
temp2 &= M23;
|
||||
RT &= M23;
|
||||
RP &= M23;
|
||||
}
|
||||
}
|
||||
/* Fix up if over flow */
|
||||
@ -1806,36 +1820,36 @@ fexp:
|
||||
}
|
||||
RA ^= M23; /* precompliment */
|
||||
RB ^= M23;
|
||||
temp2 = faccl; /* Set dividend into upper half */
|
||||
temp = facch;
|
||||
RP = faccl; /* Set dividend into upper half */
|
||||
RT = facch;
|
||||
faccl = 0;
|
||||
facch = 0;
|
||||
n = 0;
|
||||
/* DO actual divide */
|
||||
for (RK=46; RK != 0; RK--) {
|
||||
uint32 t0, t1;
|
||||
t0 = temp + RB + 1;
|
||||
t1 = temp2 + RA;
|
||||
t0 = RT + RB + 1;
|
||||
t1 = RP + RA;
|
||||
if (t0 & B0)
|
||||
t1++;
|
||||
if (n || (t1 & B0)) {
|
||||
temp = t0;
|
||||
temp2 = t1;
|
||||
RT = t0;
|
||||
RP = t1;
|
||||
facch |= 1;
|
||||
}
|
||||
facch <<= 1;
|
||||
faccl <<= 1;
|
||||
temp <<= 1;
|
||||
temp2 <<= 1;
|
||||
RT <<= 1;
|
||||
RP <<= 1;
|
||||
if (facch & B0)
|
||||
faccl |= 1;
|
||||
if (temp & B0)
|
||||
temp2 |= 1;
|
||||
n = (temp2 & B0) != 0;
|
||||
temp &= M23;
|
||||
temp2 &= M23;
|
||||
if (RT & B0)
|
||||
RP |= 1;
|
||||
n = (RP & B0) != 0;
|
||||
RT &= M23;
|
||||
RP &= M23;
|
||||
facch &= M23;
|
||||
//fprintf(stderr, "FDV3: %08o %08o %08o %08o %08o %08o %08o %02o %08o %08o %o\n\r", RA, RB, RC, faccl, facch, temp2, temp, RK,t1, t0, n);
|
||||
//fprintf(stderr, "FDV3: %08o %08o %08o %08o %08o %08o %08o %02o %08o %08o %o\n\r", RA, RB, RC, faccl, facch, RP, RT, RK,t1, t0, n);
|
||||
}
|
||||
/* If rounding and positive and negative result, adjust */
|
||||
if (((RX & 2) == 0 || f == 0) && faccl & B0) {
|
||||
@ -1908,6 +1922,12 @@ fexp:
|
||||
|
||||
case 0150:
|
||||
case 0151:
|
||||
case 0160: /* Stevenage machines */ /* Load accumulators */
|
||||
case 0161: /* Stevenage machines */ /* Store accumulators */
|
||||
case 0162: /* Stevenage machines */
|
||||
case 0163: /* Stevenage machines */ /* Stope and Display */
|
||||
case 0164: /* Stevenage machines */ /* Search List N for Word X */
|
||||
case 0165: /* Stevenage machines */ /* Parity Search */
|
||||
if (exe_mode) {
|
||||
break;
|
||||
}
|
||||
@ -1916,19 +1936,26 @@ fexp:
|
||||
RA = 0;
|
||||
switch(RB) {
|
||||
case 1: RA = SR1; break;
|
||||
case 2: RA = SR2; break;
|
||||
case 3: RA = SR3; break;
|
||||
case 64: RA = SR64; SR64 = 0; break;
|
||||
case 65: RA = SR65; SR65 = 0; break;
|
||||
case 2: ctyi_cmd(0, &RA); break;
|
||||
case 3: ctyo_cmd(0, &RA); break;
|
||||
case 64: RA = SR64; SR64 &= 003777777; break;
|
||||
case 65: RA = SR65; break;
|
||||
}
|
||||
XR[RX] = RA;
|
||||
fprintf(stderr, "RD SR %o %08o\n\r", RB, RA);
|
||||
//fprintf(stderr, "RD SR %o %08o\n\r", RB, RA);
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case 0171: /* Write special register */
|
||||
if (exe_mode) {
|
||||
fprintf(stderr, "WR SR %o %08o\n\r", RB, RA);
|
||||
//fprintf(stderr, "WR SR %o %08o\n\r", RB, RA);
|
||||
RT = 0;
|
||||
switch(RB) {
|
||||
case 2: ctyi_cmd(RA, &RT); break;
|
||||
case 3: ctyo_cmd(RA, &RT); break;
|
||||
}
|
||||
XR[RX] = RT;
|
||||
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
@ -1950,7 +1977,7 @@ fprintf(stderr, "WR SR %o %08o\n\r", RB, RA);
|
||||
Mode &= ~(EJM|AM22|EXTRC);
|
||||
Mode |= (EJM|AM22|EXTRC) & RA;
|
||||
adrmask = (Mode & AM22) ? M22 : M15;
|
||||
//fprintf(stderr, "Load limit: %08o D:=%08o %02o\n\r", RL, RD, Mode);
|
||||
fprintf(stderr, "Load limit: %08o D:=%08o %02o\n\r", RL, RD, Mode);
|
||||
#endif
|
||||
if (RF & 1) /* Check if 172 or 173 order code */
|
||||
break;
|
||||
@ -1962,7 +1989,7 @@ fprintf(stderr, "WR SR %o %08o\n\r", RB, RA);
|
||||
if ((Mode & AM22) && (RA & B3))
|
||||
Mode |= 1;
|
||||
Mem_read(RD+8, &RC, 0); /* Restore C register */
|
||||
//fprintf(stderr, "Load PC: %08o D:=%08o z=%08o\n\r", RC, RD, RA);
|
||||
fprintf(stderr, "Load PC: %08o D:=%08o z=%08o\n\r", RC, RD, RA);
|
||||
if ((Mode & AM22) == 0 && (RA & B3))
|
||||
Mode |= 1;
|
||||
BV = (RC & B0) != 0;
|
||||
@ -1976,6 +2003,15 @@ fprintf(stderr, "WR SR %o %08o\n\r", RB, RA);
|
||||
/* Fall through */
|
||||
case 0174: /* Send control character to peripheral */
|
||||
if (exe_mode) {
|
||||
RT = RB;
|
||||
chan_send_cmd(RB, RA & 077, &RB);
|
||||
fprintf(stderr, "CMD %04o %04o %08o\n\r", RT, RB, RA);
|
||||
m = (m == 0) ? 3 : (XR[m] >> 22) & 3;
|
||||
m = 6 * (3 - m);
|
||||
RB = (RB & 077) << m;
|
||||
RA &= ~(077 << m);
|
||||
RA |= RB;
|
||||
XR[RX] = RA;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
@ -1987,7 +2023,7 @@ fprintf(stderr, "WR SR %o %08o\n\r", RB, RA);
|
||||
/* Fall through */
|
||||
case 0177: /* Test Datum and Limit */
|
||||
if (exe_mode) {
|
||||
if (RA < RG || RA > RL)
|
||||
if (RA < RD || RA >= RL)
|
||||
BCarry = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
347
ICL1900/icl1900_cty.c
Normal file
347
ICL1900/icl1900_cty.c
Normal file
@ -0,0 +1,347 @@
|
||||
/* icl1900_cty.c: ICL1900 front end (console terminal) simulator
|
||||
|
||||
Copyright (c) 2018, Richard Cornwell
|
||||
|
||||
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
|
||||
RICHARD CORNWELL 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 Richard Cornwell shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Richard Cornwell
|
||||
|
||||
*/
|
||||
|
||||
#include "icl1900_defs.h"
|
||||
|
||||
extern int32 tmxr_poll;
|
||||
t_stat ctyi_svc (UNIT *uptr);
|
||||
t_stat ctyo_svc (UNIT *uptr);
|
||||
t_stat cty_reset (DEVICE *dptr);
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat cty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||
const char *cty_description (DEVICE *dptr);
|
||||
|
||||
#define CMD u3
|
||||
#define STATUS u4
|
||||
#define HOLD u5
|
||||
|
||||
#define START 01
|
||||
#define STOP 02
|
||||
#define END 000001
|
||||
#define BUSY 000040
|
||||
#define INPUT 000100
|
||||
#define CANCEL 000200
|
||||
#define ACCEPT 000400
|
||||
#define F1 001000
|
||||
#define F2 002000
|
||||
#define F3 004000
|
||||
#define F4 010000
|
||||
#define F5 020000
|
||||
|
||||
UNIT cty_unit[] = {
|
||||
{ UDATA (&ctyo_svc, TT_MODE_7P, 0), 10000 },
|
||||
{ UDATA (&ctyi_svc, TT_MODE_7P|UNIT_IDLE, 0), 0 },
|
||||
};
|
||||
|
||||
|
||||
MTAB cty_mod[] = {
|
||||
{ TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode },
|
||||
{ TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
|
||||
{ TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
|
||||
{ TT_MODE, TT_MODE_7P, "7b", "7P", &tty_set_mode },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE cty_dev = {
|
||||
"CTY", cty_unit, NULL, cty_mod,
|
||||
2, 8, 22, 1, 8, 22,
|
||||
NULL, NULL, &cty_reset,
|
||||
NULL, NULL, NULL, NULL, DEV_DEBUG, 0, dev_debug,
|
||||
NULL, NULL, &cty_help, NULL, NULL, &cty_description
|
||||
};
|
||||
|
||||
/*
|
||||
* Commands:
|
||||
* Bit 0 = start.
|
||||
* Bit 1 = stop.
|
||||
*
|
||||
* Responses:
|
||||
* Bit 0 = End of Transfer
|
||||
* Bit 5 = Busy
|
||||
* Bit 6 = Input Button Pushed.
|
||||
* Bit 7 = Cancel Button Pushed.
|
||||
* Bit 8 = Accept Button Pushed.
|
||||
* Bit 9 = F1
|
||||
* Bit 10 = F2
|
||||
* Bit 11 = F3
|
||||
* Bit 12 = F4
|
||||
* Bit 13 = F5
|
||||
*
|
||||
* 00xxxx -> 011xxxx
|
||||
* 01xxxx -> 010xxxx
|
||||
* 10xxxx -> 100xxxx
|
||||
* 11xxxx -> 101xxxx
|
||||
*
|
||||
*/
|
||||
t_stat ctyo_cmd(uint32 cmd, uint32 *resp) {
|
||||
if ((cmd & START) != 0 && (cty_unit[0].STATUS & BUSY) == 0)
|
||||
sim_activate(&cty_unit[0], cty_unit[0].wait);
|
||||
cty_unit[0].CMD |= cmd;
|
||||
*resp = cty_unit[0].STATUS;
|
||||
cty_unit[0].STATUS &= BUSY;
|
||||
chan_clr_done(3);
|
||||
}
|
||||
|
||||
t_stat ctyi_cmd(uint32 cmd, uint32 *resp) {
|
||||
cty_unit[1].CMD |= cmd;
|
||||
*resp = cty_unit[1].STATUS;
|
||||
cty_unit[1].STATUS &= BUSY;
|
||||
chan_clr_done(2);
|
||||
}
|
||||
|
||||
t_stat ctyo_svc (UNIT *uptr)
|
||||
{
|
||||
t_stat r;
|
||||
uint8 ch;
|
||||
int eor;
|
||||
|
||||
if (uptr->CMD & START) {
|
||||
uptr->STATUS &= ~END;
|
||||
uptr->STATUS |= BUSY;
|
||||
chan_clr_done(3);
|
||||
}
|
||||
if (uptr->CMD & STOP) {
|
||||
uptr->STATUS |= END;
|
||||
uptr->STATUS &= ~BUSY;
|
||||
chan_set_done(3);
|
||||
}
|
||||
uptr->CMD = 0;
|
||||
/* Check if we had a held characteter */
|
||||
if (uptr->HOLD != 0) {
|
||||
if ((r = sim_putchar_s (uptr->HOLD)) == SCPE_STALL) {
|
||||
r = SCPE_OK;
|
||||
} else {
|
||||
if (uptr->HOLD == '\r')
|
||||
uptr->HOLD = '\n';
|
||||
else
|
||||
uptr->HOLD = 0;
|
||||
}
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return r;
|
||||
}
|
||||
|
||||
if (uptr->STATUS & BUSY) {
|
||||
eor = chan_output_char(3, &ch, 0);
|
||||
switch (ch & 060) {
|
||||
case 000: ch = 0060 | (ch & 017); break;
|
||||
case 020: ch = 0040 | (ch & 017); break;
|
||||
case 040: ch = 0100 | (ch & 017); break;
|
||||
case 060: ch = 0120 | (ch & 017); break;
|
||||
}
|
||||
if (ch == 0137) {
|
||||
ch = '\r';
|
||||
uptr->HOLD = '\n';
|
||||
}
|
||||
ch = sim_tt_outcvt ( ch, TT_GET_MODE (uptr->flags)) ;
|
||||
if ((r = sim_putchar_s (ch)) == SCPE_STALL) { /* output; error? */
|
||||
uptr->HOLD = ch;
|
||||
r = SCPE_OK;
|
||||
}
|
||||
if (eor) {
|
||||
uptr->STATUS &= ~BUSY;
|
||||
uptr->STATUS |= END;
|
||||
chan_set_done(3);
|
||||
}
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ctyi_svc (UNIT *uptr)
|
||||
{
|
||||
t_stat r;
|
||||
uint8 ch;
|
||||
int eor;
|
||||
|
||||
sim_clock_coschedule (uptr, tmxr_poll);
|
||||
|
||||
if (uptr->CMD & START) {
|
||||
uptr->STATUS &= ~END;
|
||||
uptr->STATUS |= BUSY;
|
||||
chan_clr_done(2);
|
||||
}
|
||||
if (uptr->CMD & STOP) {
|
||||
uptr->STATUS |= END;
|
||||
uptr->STATUS &= ~BUSY;
|
||||
chan_set_done(2);
|
||||
}
|
||||
uptr->CMD = 0;
|
||||
/* Handle input */
|
||||
|
||||
r = sim_poll_kbd();
|
||||
if (r & SCPE_KFLAG) {
|
||||
ch = 0177 & sim_tt_inpcvt(r & 0377, TT_GET_MODE (uptr->flags));
|
||||
if (uptr->HOLD) {
|
||||
if (ch >= '1' && ch <= '5') {
|
||||
chan_set_done(2);
|
||||
uptr->STATUS |= (F1 << (ch - '1'));
|
||||
} else {
|
||||
sim_putchar('\007');
|
||||
}
|
||||
uptr->HOLD = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((uptr->STATUS & BUSY) != 0) {
|
||||
/* Handle end of buffer */
|
||||
switch (ch) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
sim_debug(DEBUG_DATA, &cty_dev, ": ent\n");
|
||||
sim_putchar('\r');
|
||||
sim_putchar('\n');
|
||||
uptr->STATUS |= ACCEPT|END;
|
||||
uptr->STATUS &= ~BUSY;
|
||||
chan_set_done(2);
|
||||
break;
|
||||
|
||||
case 033: /* function key <escape>n key */
|
||||
uptr->HOLD = 1;
|
||||
break;
|
||||
|
||||
case 030: /* ^X Post input interrupt */
|
||||
sim_debug(DEBUG_CMD, &cty_dev, ": inp\n");
|
||||
uptr->STATUS |= INPUT|END;
|
||||
uptr->STATUS &= ~BUSY;
|
||||
uptr->HOLD = 0;
|
||||
chan_set_done(2);
|
||||
break;
|
||||
|
||||
case 03: /* ^C */
|
||||
case 025: /* ^U clear line */
|
||||
uptr->STATUS |= CANCEL|END;
|
||||
uptr->STATUS &= ~BUSY;
|
||||
uptr->HOLD = 0;
|
||||
chan_set_done(2);
|
||||
break;
|
||||
|
||||
default:
|
||||
sim_debug(DEBUG_DATA, &cty_dev, ": key '%c'\n", ch);
|
||||
if (ch >= 0140)
|
||||
ch -= 040;
|
||||
if (ch >= 0100)
|
||||
ch -= 040;
|
||||
else if (ch >= 060)
|
||||
ch -= 060;
|
||||
else if (ch >= 040)
|
||||
ch -= 020;
|
||||
else {
|
||||
sim_putchar('\007');
|
||||
break;
|
||||
}
|
||||
eor = chan_input_char(2, &ch, 0);
|
||||
switch (ch & 060) {
|
||||
case 000: ch = 0060 | (ch & 017); break;
|
||||
case 020: ch = 0040 | (ch & 017); break;
|
||||
case 040: ch = 0100 | (ch & 017); break;
|
||||
case 060: ch = 0120 | (ch & 017); break;
|
||||
}
|
||||
ch = sim_tt_outcvt ( ch, TT_GET_MODE (uptr->flags)) ;
|
||||
sim_putchar (ch);
|
||||
if (eor) {
|
||||
uptr->STATUS &= ~BUSY;
|
||||
uptr->STATUS |= END;
|
||||
chan_set_done(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Handle end of buffer */
|
||||
switch (ch) {
|
||||
case 033: /* function key <escape>n key */
|
||||
uptr->HOLD = 1;
|
||||
break;
|
||||
|
||||
case 030: /* ^X Post input interrupt */
|
||||
sim_debug(DEBUG_CMD, &cty_dev, ": inp\n");
|
||||
uptr->STATUS |= INPUT;
|
||||
uptr->HOLD = 0;
|
||||
chan_set_done(2);
|
||||
break;
|
||||
|
||||
case 03: /* ^C */
|
||||
case 025: /* ^U clear line */
|
||||
uptr->STATUS |= CANCEL;
|
||||
uptr->HOLD = 0;
|
||||
chan_set_done(2);
|
||||
break;
|
||||
|
||||
default:
|
||||
sim_debug(DEBUG_DATA, &cty_dev, ": key '%c'\n", ch);
|
||||
sim_putchar('\007');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset */
|
||||
|
||||
t_stat cty_reset (DEVICE *dptr)
|
||||
{
|
||||
cty_unit[0].CMD = 0;
|
||||
cty_unit[1].CMD = 0;
|
||||
cty_unit[0].STATUS = 0;
|
||||
cty_unit[1].STATUS = 0;
|
||||
chan_clr_done(2);
|
||||
chan_clr_done(3);
|
||||
sim_clock_coschedule (&cty_unit[1], tmxr_poll);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||
{
|
||||
cty_unit[0].flags = (cty_unit[0].flags & ~TT_MODE) | val;
|
||||
cty_unit[1].flags = (cty_unit[1].flags & ~TT_MODE) | val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
{
|
||||
fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n");
|
||||
fprintf (st, " mode input characters output characters\n\n");
|
||||
fprintf (st, " UC lower case converted lower case converted to upper case,\n");
|
||||
fprintf (st, " to upper case, high-order bit cleared,\n");
|
||||
fprintf (st, " high-order bit cleared non-printing characters suppressed\n");
|
||||
fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n");
|
||||
fprintf (st, " non-printing characters suppressed\n");
|
||||
fprintf (st, " 7B high-order bit cleared high-order bit cleared\n");
|
||||
fprintf (st, " 8B no changes no changes\n\n");
|
||||
fprintf (st, "The default mode is 7P. In addition, each line can be configured to\n");
|
||||
fprintf (st, "behave as though it was attached to a dataset, or hardwired to a terminal:\n\n");
|
||||
fprint_reg_help (st, &cty_dev);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
const char *cty_description (DEVICE *dptr)
|
||||
{
|
||||
return "Console TTY Line";
|
||||
|
||||
}
|
||||
|
||||
@ -57,6 +57,8 @@ extern uint32 M[]; /* Main Memory */
|
||||
|
||||
extern DEBTAB dev_debug[];
|
||||
|
||||
extern uint32 SR64;
|
||||
extern uint32 SR65;
|
||||
|
||||
/* Returns from device commands */
|
||||
#define SCPE_BUSY (1) /* Device is active */
|
||||
@ -174,6 +176,8 @@ t_opcode;
|
||||
#define B1 020000000
|
||||
#define B2 010000000
|
||||
#define B3 004000000
|
||||
#define B4 002000000
|
||||
#define B5 001000000
|
||||
#define B8 000100000
|
||||
#define B15 000001000
|
||||
#define B16 000000400
|
||||
@ -190,6 +194,8 @@ t_opcode;
|
||||
|
||||
#define CHAR_DEV 0 /* Device transfers via characters */
|
||||
#define WORD_DEV 1 /* Device transfers via words */
|
||||
#define SPEC_HES 2 /* Special transfer */
|
||||
#define LONG_BLK 4 /* Long block device */
|
||||
|
||||
struct icl_dib {
|
||||
uint8 channel; /* Channel number */
|
||||
@ -200,11 +206,13 @@ struct icl_dib {
|
||||
typedef struct icl_dib DIB;
|
||||
|
||||
/* Hessitation operations */
|
||||
int chan_write_char(uint8 channel, uint8 data);
|
||||
int chan_read_char(uint8 channel, uint8 *data);
|
||||
int chan_write_word(uint8 channel, uint32 data);
|
||||
int chan_read_word(uint8 channel, uint32 *data);
|
||||
int chan_end(uint8 channel);
|
||||
extern void chan_send_cmd(int dev, uint32 cmd, uint32 *resp);
|
||||
extern int chan_input_char(int dev, uint8 *data, int eor);
|
||||
extern int chan_output_char(int dev, uint8 *data, int eor);
|
||||
extern int chan_input_word(int dev, uint32 *data, int eor);
|
||||
extern int chan_output_word(int dev, uint32 *data, int eor);
|
||||
extern void chan_set_done(int dev);
|
||||
extern void chan_clr_done(int dev);
|
||||
|
||||
/* Console tty device routines */
|
||||
extern t_stat ctyi_cmd(uint32 cmd, uint32 *resp);
|
||||
|
||||
365
ICL1900/icl1900_stdio.c
Normal file
365
ICL1900/icl1900_stdio.c
Normal file
@ -0,0 +1,365 @@
|
||||
/* icl1900_stdio.c: ICL 1900 standard I/O devices
|
||||
|
||||
Copyright (c) 2018, Richard Cornwell
|
||||
|
||||
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
|
||||
RICHARD CORNWELL 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "icl1900_defs.h"
|
||||
|
||||
/* Define style bits */
|
||||
|
||||
#define OUTPUT B0 /* Input/Output flag */
|
||||
#define BACKWARD B1 /* Forward/Backword */
|
||||
#define WORDCCW B2 /* Character/Word */
|
||||
#define MULTICHN B3 /* Single/Multi Channel */
|
||||
#define CWRECHARGE B4 /* Recharge CW when empty */
|
||||
#define GATHER B5 /* Gather */
|
||||
|
||||
|
||||
DIB *devs[32]; /* Pointer to device DIB entry */
|
||||
|
||||
/* Fake DIB entries for the CTY devices */
|
||||
DIB ctyi_dib = { 2, CHAR_DEV, ctyi_cmd};
|
||||
DIB ctyo_dib = { 3, CHAR_DEV, ctyo_cmd};
|
||||
DIB nul1_dib = { 22, 0, 0};
|
||||
DIB nul2_dib = { 23, 0, 0};
|
||||
|
||||
uint32 cw0; /* Holding registers for current control word */
|
||||
uint32 cw1;
|
||||
|
||||
t_stat
|
||||
chan_set_devs()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Clear device table */
|
||||
for (i = 0; i < sizeof(devs)/sizeof(DIB *); i++)
|
||||
devs[i] = NULL;
|
||||
|
||||
devs[22-4] = &nul1_dib; /* Add in hidden channels */
|
||||
devs[23-4] = &nul2_dib;
|
||||
/* Scan all devices and assign to channel */
|
||||
for(i = 0; sim_devices[i] != NULL; i++) {
|
||||
DIB *dibp = (DIB *) sim_devices[i]->ctxt;
|
||||
int chan;
|
||||
|
||||
/* Check if device a channel device */
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* If device is disabled, don't add it */
|
||||
if (sim_devices[i]->flags & DEV_DIS)
|
||||
continue;
|
||||
chan = dibp->channel - 4;
|
||||
if (chan < 0)
|
||||
continue;
|
||||
if (devs[chan] != NULL) {
|
||||
fprintf(stderr, "Conflict between devices %d %s\n", chan, sim_devices[i]->name);
|
||||
} else {
|
||||
devs[chan] = dibp;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Set the device onto a given channel */
|
||||
t_stat
|
||||
set_chan(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
int newchan;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL)
|
||||
return SCPE_ARG;
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dptr = find_dev_from_unit(uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
|
||||
if (dibp == NULL)
|
||||
return SCPE_IERR;
|
||||
newchan = get_uint(cptr, 10, 37, &r);
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
if (newchan < 4) /* Lowest channel is 4 */
|
||||
return SCPE_ARG;
|
||||
newchan -= 4;
|
||||
if (dibp == devs[dibp->channel-4])
|
||||
devs[dibp->channel-4] = NULL;
|
||||
/* If device is disabled, set to whatever the user wants */
|
||||
if (dptr->flags & DEV_DIS) {
|
||||
dibp->channel = newchan;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (devs[newchan] != NULL) {
|
||||
devs[newchan] = dibp;
|
||||
dibp->channel = newchan+4;
|
||||
return SCPE_OK;
|
||||
} else {
|
||||
fprintf(stderr, "Device already on channel %d\n", newchan+4);
|
||||
devs[dibp->channel] = dibp;
|
||||
}
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* Print the channel the device is on */
|
||||
t_stat
|
||||
get_chan(FILE *st, UNIT *uptr, int32 v, CONST void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
int chan;
|
||||
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dptr = find_dev_from_unit(uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
return SCPE_IERR;
|
||||
fprintf(st, "Chan=%d", dibp->channel);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
int
|
||||
get_ccw(int dev, uint32 *addr, uint8 type) {
|
||||
int cw_addr = 256+4*dev;
|
||||
#if 0
|
||||
cw0 = M[64+dev];
|
||||
#endif
|
||||
cw0 = M[cw_addr];
|
||||
cw1 = M[cw_addr+1];
|
||||
*addr = cw1;
|
||||
if (cw0 & WORDCCW) {
|
||||
if (cw0 & BACKWARD)
|
||||
cw1 = ((cw1 + M22) & M22) | (cw1 & CMASK);
|
||||
else
|
||||
cw1 = ((cw1 + 1) & M22) | (cw1 & CMASK);
|
||||
} else {
|
||||
if (cw0 & BACKWARD) {
|
||||
if (cw1 & CMASK) {
|
||||
cw1 -= B1;
|
||||
} else {
|
||||
cw1 = ((cw1 - 1) & M22) | CMASK;
|
||||
}
|
||||
} else {
|
||||
if ((cw1 & CMASK) == CMASK) {
|
||||
cw1 = (cw1 + 1) & M22;
|
||||
} else {
|
||||
cw1 += B1;
|
||||
}
|
||||
}
|
||||
}
|
||||
cw0 = ((cw0 - 1) & M15) | (cw0 & CNTMSK);
|
||||
if ((cw0 & M15) == 0) {
|
||||
if ((cw0 & (CWRECHARGE|GATHER)) == (CWRECHARGE)) {
|
||||
cw0 = M[cw_addr+2];
|
||||
cw1 = M[cw_addr+3];
|
||||
} else if ((cw0 & GATHER) != 0) {
|
||||
int a;
|
||||
if ((cw0 & CWRECHARGE) != 0)
|
||||
M[cw_addr+3] = M[cw_addr+2];
|
||||
a = M[cw_addr+3];
|
||||
cw0 = M[a & M22];
|
||||
cw1 = M[(a + 1) & M22];
|
||||
M[cw_addr+3] = ((a + 2) & M22) | (a & CMASK);
|
||||
}
|
||||
M[cw_addr] = cw0;
|
||||
M[cw_addr+1] = cw1;
|
||||
return (cw0 & M15) == 0;
|
||||
}
|
||||
M[cw_addr] = cw0;
|
||||
M[cw_addr+1] = cw1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Hessitation operations */
|
||||
void
|
||||
chan_send_cmd(int dev, uint32 cmd, uint32 *resp) {
|
||||
DIB *dibp = NULL;
|
||||
int d = dev & 077;
|
||||
|
||||
if (dev >= 4 && dev <= 36)
|
||||
dibp = devs[d - 4];
|
||||
else if (dev == 3)
|
||||
dibp = &ctyo_dib;
|
||||
else if (dev == 2)
|
||||
dibp = &ctyi_dib;
|
||||
|
||||
*resp = 0;
|
||||
if (dibp != NULL && dibp->dev_cmd != NULL) {
|
||||
t_stat r;
|
||||
|
||||
r = (dibp->dev_cmd)((dev & 07700) | cmd, resp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transfer date between device and memory */
|
||||
int
|
||||
chan_input_char(int dev, uint8 *data, int eor) {
|
||||
int r;
|
||||
int c;
|
||||
DIB *dibp = NULL;
|
||||
uint32 addr;
|
||||
uint32 mb;
|
||||
|
||||
|
||||
/* Figure out DIB to find out type of device */
|
||||
if (dev >= 4 && dev <= 36)
|
||||
dibp = devs[dev - 4];
|
||||
else if (dev == 3)
|
||||
dibp = &ctyo_dib;
|
||||
else if (dev == 2)
|
||||
dibp = &ctyi_dib;
|
||||
|
||||
/* Make sure device assigne here */
|
||||
if (dibp == NULL || dibp->dev_cmd == NULL)
|
||||
return -1;
|
||||
|
||||
/* Check if right type */
|
||||
if ((dibp->type & WORD_DEV) != 0)
|
||||
return -2;
|
||||
|
||||
/* Get address of next character. */
|
||||
r = get_ccw(dev, &addr, dibp->type);
|
||||
c = (addr >> 22) & 3;
|
||||
c = 6 * (3 - c);
|
||||
mb = M[addr & M22];
|
||||
mb &= ~(077 << c);
|
||||
mb |= ((uint32)(*data) & 077) << c;
|
||||
M[addr & M22] = mb;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
chan_output_char(int dev, uint8 *data, int eor) {
|
||||
int r;
|
||||
int c;
|
||||
DIB *dibp = NULL;
|
||||
uint32 addr;
|
||||
uint32 mb;
|
||||
|
||||
|
||||
/* Figure out DIB to find out type of device */
|
||||
if (dev >= 4 && dev <= 36)
|
||||
dibp = devs[dev - 4];
|
||||
else if (dev == 3)
|
||||
dibp = &ctyo_dib;
|
||||
else if (dev == 2)
|
||||
dibp = &ctyi_dib;
|
||||
|
||||
/* Make sure device assigne here */
|
||||
if (dibp == NULL || dibp->dev_cmd == NULL)
|
||||
return -1;
|
||||
|
||||
/* Check if right type */
|
||||
if ((dibp->type & WORD_DEV) != 0)
|
||||
return -2;
|
||||
|
||||
/* Get address of next character. */
|
||||
r = get_ccw(dev, &addr, dibp->type);
|
||||
c = (addr >> 22) & 3;
|
||||
c = 6 * (3 - c);
|
||||
mb = M[addr & M22];
|
||||
*data = (uint8)(mb >> c) & 077;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
chan_input_word(int dev, uint32 *data, int eor) {
|
||||
int r;
|
||||
DIB *dibp = NULL;
|
||||
uint32 addr;
|
||||
|
||||
|
||||
/* Figure out DIB to find out type of device */
|
||||
if (dev >= 4 && dev <= 36)
|
||||
dibp = devs[dev - 4];
|
||||
else if (dev == 3)
|
||||
dibp = &ctyo_dib;
|
||||
else if (dev == 2)
|
||||
dibp = &ctyi_dib;
|
||||
|
||||
/* Make sure device assigne here */
|
||||
if (dibp == NULL || dibp->dev_cmd == NULL)
|
||||
return -1;
|
||||
|
||||
/* Check if right type */
|
||||
if ((dibp->type & WORD_DEV) == 0)
|
||||
return -2;
|
||||
|
||||
/* Get address of next word. */
|
||||
r = get_ccw(dev, &addr, dibp->type);
|
||||
M[addr & M22] = *data;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
chan_output_word(int dev, uint32 *data, int eor) {
|
||||
int r;
|
||||
DIB *dibp = NULL;
|
||||
uint32 addr;
|
||||
|
||||
|
||||
/* Figure out DIB to find out type of device */
|
||||
if (dev >= 4 && dev <= 36)
|
||||
dibp = devs[dev - 4];
|
||||
else if (dev == 3)
|
||||
dibp = &ctyo_dib;
|
||||
else if (dev == 2)
|
||||
dibp = &ctyi_dib;
|
||||
|
||||
/* Make sure device assigne here */
|
||||
if (dibp == NULL || dibp->dev_cmd == NULL)
|
||||
return -1;
|
||||
|
||||
/* Check if right type */
|
||||
if ((dibp->type & WORD_DEV) == 0)
|
||||
return -2;
|
||||
|
||||
/* Get address of next word. */
|
||||
r = get_ccw(dev, &addr, dibp->type);
|
||||
*data = M[addr & M22];
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
chan_set_done(int dev) {
|
||||
if (dev < 22)
|
||||
SR64 |= B2 >> dev;
|
||||
else
|
||||
SR65 |= B1 >> (dev - 24);
|
||||
}
|
||||
|
||||
void
|
||||
chan_clr_done(int dev) {
|
||||
if (dev < 22)
|
||||
SR64 &= ~(B2 >> dev);
|
||||
else
|
||||
SR65 &= ~(B1 >> (dev - 24));
|
||||
}
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ int32 sim_emax = 1;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
// &cty_dev,
|
||||
&cty_dev,
|
||||
#if NUM_DEVS_CDR > 0
|
||||
&cdr_dev,
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user