1
0
mirror of https://github.com/simh/simh.git synced 2026-01-25 19:56:25 +00:00

Notes For V3.5-0

The source set has been extensively overhauled.  For correct
viewing, set Visual C++ or Emacs to have tab stops every 4
characters.

1. New Features in 3.4-1

1.1 All Ethernet devices

- Added Windows user-defined adapter names (from Timothe Litt)

1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors

- Added support for SET <unit>n DISCONNECT

1.3 VAX

- Added latent QDSS support
- Revised autoconfigure to handle QDSS

1.4 PDP-11

- Revised autoconfigure to handle more casees

2. Bugs Fixed in 3.4-1

2.1 SCP and libraries

- Trim trailing spaces on all input (for example, attach file names)
- Fixed sim_sock spurious SIGPIPE error in Unix/Linux
- Fixed sim_tape misallocation of TPC map array for 64b simulators

2.2 1401

- Fixed bug, CPU reset was clearing SSB through SSG

2.3 PDP-11

- Fixed bug in VH vector display routine
- Fixed XU runt packet processing (found by Tim Chapman)

2.4 Interdata

- Fixed bug in SHOW PAS CONN/STATS
- Fixed potential integer overflow exception in divide

2.5 SDS

- Fixed bug in SHOW MUX CONN/STATS

2.6 HP

- Fixed bug in SHOW MUX CONN/STATS

2.7 PDP-8

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.8 PDP-18b

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.9 Nova, Eclipse

- Fixed potential integer overflow exception in divide
This commit is contained in:
Bob Supnik
2005-09-09 18:09:00 -07:00
committed by Mark Pizzolato
parent ec60bbf329
commit b7c1eae41f
257 changed files with 107140 additions and 97195 deletions

View File

@@ -19,19 +19,20 @@
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 Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
cpu LGP-30 [LGP-21] CPU
cpu LGP-30 [LGP-21] CPU
04-Jan-05 RMS Modified VM pointer setup
04-Sep-05 RMS Fixed missing returns (found by Peter Schorn)
04-Jan-05 RMS Modified VM pointer setup
The system state for the LGP-30 [LGP-21] is:
A<0:31> accumulator
C<0:11> counter (PC)
OVF overflow flag [LGP-21 only]
A<0:31> accumulator
C<0:11> counter (PC)
OVF overflow flag [LGP-21 only]
The LGP-30 [LGP-21] has just one instruction format:
@@ -43,58 +44,57 @@
LGP-30 instructions:
<0,12:15> operation
<0,12:15> operation
0 stop
1 A <- M[ea]
2 M[ea]<addr> <- A<addr>
3 M[ea]<addr> <- C + 1
4 input
5 A <- A / M[ea]
6 A <- A * M[ea], low result
7 A <- A * M[ea], high result
8 output
9 A <- A & M[ea]
A C <- ea
B C <- ea if A < 0
-B C <- ea if (A < 0) || T-switch set
C M[ea] <- A
D M[ea] <- A, A <- 0
E A <- A + M[ea]
F A <- A - M[ea]
0 stop
1 A <- M[ea]
2 M[ea]<addr> <- A<addr>
3 M[ea]<addr> <- C + 1
4 input
5 A <- A / M[ea]
6 A <- A * M[ea], low result
7 A <- A * M[ea], high result
8 output
9 A <- A & M[ea]
A C <- ea
B C <- ea if A < 0
-B C <- ea if (A < 0) || T-switch set
C M[ea] <- A
D M[ea] <- A, A <- 0
E A <- A + M[ea]
F A <- A - M[ea]
LGP-21 instructions:
<0,12:15> operation
<0,12:15> operation
0 stop; sense and skip
-0 stop; sense overflow and skip
1 A <- M[ea]
2 M[ea]<addr> <- A<addr>
3 M[ea]<addr> <- C + 1
4 6b input
-4 4b input
5 A <- A / M[ea]
6 A <- A * M[ea], low result
7 A <- A * M[ea], high result
8 6b output
-8 4b output
9 A <- A & M[ea]
A C <- ea
B C <- ea if A < 0
-B C <- ea if (A < 0) || T-switch set
C M[ea] <- A
D M[ea] <- A, A <- 0
E A <- A + M[ea]
F A <- A - M[ea]
0 stop; sense and skip
-0 stop; sense overflow and skip
1 A <- M[ea]
2 M[ea]<addr> <- A<addr>
3 M[ea]<addr> <- C + 1
4 6b input
-4 4b input
5 A <- A / M[ea]
6 A <- A * M[ea], low result
7 A <- A * M[ea], high result
8 6b output
-8 4b output
9 A <- A & M[ea]
A C <- ea
B C <- ea if A < 0
-B C <- ea if (A < 0) || T-switch set
C M[ea] <- A
D M[ea] <- A, A <- 0
E A <- A + M[ea]
F A <- A - M[ea]
The LGP-30 [LGP-21] has 4096 32b words of memory. The low order
bit is always read and stored as 0. The LGP-30 uses a drum for
memory, with 64 tracks of 64 words. The LGP-21 uses a disk for
memory, with 32 tracks of 128 words.
*/
/* This routine is the instruction decode routine for the LGP-30
This routine is the instruction decode routine for the LGP-30
[LGP-21]. It is called from the simulator control program to
execute instructions in simulated memory, starting at the simulated
PC. It runs until 'reason' is set non-zero.
@@ -103,10 +103,10 @@
1. Reasons to stop. The simulator can be stopped by:
STOP instruction
breakpoint encountered
overflow [LGP-30]
I/O error in I/O simulator
STOP instruction
breakpoint encountered
overflow [LGP-30]
I/O error in I/O simulator
2. Interrupts. There are no interrupts.
@@ -115,40 +115,40 @@
4. Adding I/O devices. The LGP-30 could not support additional
I/O devices. The LGP-21 could but none are known.
*/
#include "lgp_defs.h"
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = (PC - 1) & AMASK;
#define M16 0xFFFF
#define M32 0xFFFFFFFF
#define NEG(x) ((~(x) + 1) & DMASK)
#define ABS(x) (((x) & SIGN)? NEG (x): (x))
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = (PC - 1) & AMASK;
#define M16 0xFFFF
#define M32 0xFFFFFFFF
#define NEG(x) ((~(x) + 1) & DMASK)
#define ABS(x) (((x) & SIGN)? NEG (x): (x))
uint32 M[MEMSIZE] = { 0 }; /* memory */
uint32 PC = 0; /* counter */
uint32 A = 0; /* accumulator */
uint32 IR = 0; /* instr register */
uint32 OVF = 0; /* overflow indicator */
uint32 t_switch = 0; /* transfer switch */
uint32 bp32 = 0; /* BP32 switch */
uint32 bp16 = 0; /* BP16 switch */
uint32 bp8 = 0; /* BP8 switch */
uint32 bp4 = 0; /* BP4 switch */
uint32 inp_strt = 0; /* input started */
uint32 inp_done = 0; /* input done */
uint32 out_strt = 0; /* output started */
uint32 out_done = 0; /* output done */
uint32 lgp21_sov = 0; /* LGP-21 sense pending */
uint32 M[MEMSIZE] = { 0 }; /* memory */
uint32 PC = 0; /* counter */
uint32 A = 0; /* accumulator */
uint32 IR = 0; /* instr register */
uint32 OVF = 0; /* overflow indicator */
uint32 t_switch = 0; /* transfer switch */
uint32 bp32 = 0; /* BP32 switch */
uint32 bp16 = 0; /* BP16 switch */
uint32 bp8 = 0; /* BP8 switch */
uint32 bp4 = 0; /* BP4 switch */
uint32 inp_strt = 0; /* input started */
uint32 inp_done = 0; /* input done */
uint32 out_strt = 0; /* output started */
uint32 out_done = 0; /* output done */
uint32 lgp21_sov = 0; /* LGP-21 sense pending */
int32 delay = 0;
int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
extern int32 sim_interval;
extern int32 sim_int_char;
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern int32 sim_step;
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
@@ -170,94 +170,103 @@ uint32 shift_in (uint32 a, uint32 dat, uint32 sh4);
extern t_stat op_p (uint32 dev, uint32 ch);
extern t_stat op_i (uint32 dev, uint32 ch, uint32 sh4);
extern void lgp_vm_init (void);
/* CPU data structures
cpu_dev CPU device descriptor
cpu_unit CPU unit descriptor
cpu_reg CPU register list
cpu_mod CPU modifiers list
cpu_dev CPU device descriptor
cpu_unit CPU unit descriptor
cpu_reg CPU register list
cpu_mod CPU modifiers list
*/
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_IN4B+UNIT_TTSS_D, MEMSIZE) };
REG cpu_reg[] = {
{ DRDATA (C, PC, 12), REG_VMAD },
{ HRDATA (A, A, 32), REG_VMIO },
{ HRDATA (IR, IR, 32), REG_VMIO },
{ FLDATA (OVF, OVF, 0) },
{ FLDATA (TSW, t_switch, 0) },
{ FLDATA (BP32, bp32, 0) },
{ FLDATA (BP16, bp16, 0) },
{ FLDATA (BP8, bp8, 0) },
{ FLDATA (BP4, bp4, 0) },
{ FLDATA (INPST, inp_strt, 0) },
{ FLDATA (INPDN, inp_done, 0) },
{ FLDATA (OUTST, out_strt, 0) },
{ FLDATA (OUTDN, out_done, 0) },
{ DRDATA (DELAY, delay, 7) },
{ BRDATA (CQ, pcq, 16, 12, PCQ_SIZE), REG_RO + REG_CIRC },
{ HRDATA (CQP, pcq_p, 6), REG_HRO },
{ HRDATA (WRU, sim_int_char, 8) },
{ NULL } };
{ DRDATA (C, PC, 12), REG_VMAD },
{ HRDATA (A, A, 32), REG_VMIO },
{ HRDATA (IR, IR, 32), REG_VMIO },
{ FLDATA (OVF, OVF, 0) },
{ FLDATA (TSW, t_switch, 0) },
{ FLDATA (BP32, bp32, 0) },
{ FLDATA (BP16, bp16, 0) },
{ FLDATA (BP8, bp8, 0) },
{ FLDATA (BP4, bp4, 0) },
{ FLDATA (INPST, inp_strt, 0) },
{ FLDATA (INPDN, inp_done, 0) },
{ FLDATA (OUTST, out_strt, 0) },
{ FLDATA (OUTDN, out_done, 0) },
{ DRDATA (DELAY, delay, 7) },
{ BRDATA (CQ, pcq, 16, 12, PCQ_SIZE), REG_RO + REG_CIRC },
{ HRDATA (CQP, pcq_p, 6), REG_HRO },
{ HRDATA (WRU, sim_int_char, 8) },
{ NULL }
};
MTAB cpu_mod[] = {
{ UNIT_LGP21, UNIT_LGP21, "LGP-21", "LGP21", &cpu_set_model, &cpu_show_model },
{ UNIT_LGP21, 0, "LGP-30", "LGP30", &cpu_set_model, &cpu_show_model },
{ UNIT_TTSS_D, UNIT_TTSS_D, 0, "TRACK" },
{ UNIT_TTSS_D, 0, 0, "NORMAL" },
{ UNIT_LGPH_D, UNIT_LGPH_D, 0, "LGPHEX" },
{ UNIT_LGPH_D, 0, 0, "STANDARDHEX" },
{ UNIT_MANI, UNIT_MANI, NULL, "MANUAL" },
{ UNIT_MANI, 0, NULL, "TAPE" },
{ UNIT_IN4B, UNIT_IN4B, NULL, "4B", &cpu_set_30opt },
{ UNIT_IN4B, 0, NULL, "6B", &cpu_set_30opt },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "INPUT", &cpu_set_30opt_i },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "OUTPUT", &cpu_set_30opt_o },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "EXECUTE", &cpu_set_exec },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "FILL", &cpu_set_fill },
{ 0 } };
{ UNIT_LGP21, UNIT_LGP21, "LGP-21", "LGP21", &cpu_set_model, &cpu_show_model },
{ UNIT_LGP21, 0, "LGP-30", "LGP30", &cpu_set_model, &cpu_show_model },
{ UNIT_TTSS_D, UNIT_TTSS_D, 0, "TRACK" },
{ UNIT_TTSS_D, 0, 0, "NORMAL" },
{ UNIT_LGPH_D, UNIT_LGPH_D, 0, "LGPHEX" },
{ UNIT_LGPH_D, 0, 0, "STANDARDHEX" },
{ UNIT_MANI, UNIT_MANI, NULL, "MANUAL" },
{ UNIT_MANI, 0, NULL, "TAPE" },
{ UNIT_IN4B, UNIT_IN4B, NULL, "4B", &cpu_set_30opt },
{ UNIT_IN4B, 0, NULL, "6B", &cpu_set_30opt },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "INPUT", &cpu_set_30opt_i },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "OUTPUT", &cpu_set_30opt_o },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "EXECUTE", &cpu_set_exec },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "FILL", &cpu_set_fill },
{ 0 }
};
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 10, 12, 1, 16, 32,
&cpu_ex, &cpu_dep, &cpu_reset,
NULL, NULL, NULL };
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 10, 12, 1, 16, 32,
&cpu_ex, &cpu_dep, &cpu_reset,
NULL, NULL, NULL
};
/* Timing tables */
/* Optimization minima and maxima
Z B Y R I D N M P E U T H C A S */
Z B Y R I D N M P E U T H C A S */
static const int32 min_30[16] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
};
static const int32 max_30[16] = {
7, 7, 7, 7, 7, 5, 8, 6, 7, 7, 0, 0, 7, 7, 7, 7 };
7, 7, 7, 7, 7, 5, 8, 6, 7, 7, 0, 0, 7, 7, 7, 7
};
static const int32 min_21[16] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
};
static const int32 max_21[16] = {
0, 16, 16, 16, 0, 58, 81, 79, 0, 16, 0, 0, 16, 16, 16, 16 };
0, 16, 16, 16, 0, 58, 81, 79, 0, 16, 0, 0, 16, 16, 16, 16
};
static const uint32 log_to_phys_30[NSC_30] = { /* drum interlace chart */
0, 57, 50, 43, 36, 29, 22, 15, 8 ,
1, 58, 51, 44, 37, 30, 23, 16, 9 ,
2, 59, 52, 45, 38, 31, 24, 17, 10,
3, 60, 53, 46, 39, 32, 25, 18, 11,
4, 61, 54, 47, 40, 33, 26, 19, 12,
5, 62, 55, 48, 41, 32, 27, 20, 13,
6, 63, 56, 49, 42, 33, 28, 21, 14,
7 };
static const uint32 log_to_phys_30[NSC_30] = { /* drum interlace chart */
0, 57, 50, 43, 36, 29, 22, 15, 8 ,
1, 58, 51, 44, 37, 30, 23, 16, 9 ,
2, 59, 52, 45, 38, 31, 24, 17, 10,
3, 60, 53, 46, 39, 32, 25, 18, 11,
4, 61, 54, 47, 40, 33, 26, 19, 12,
5, 62, 55, 48, 41, 32, 27, 20, 13,
6, 63, 56, 49, 42, 33, 28, 21, 14,
7
};
static const uint32 log_to_phys_21[NSC_21] = { /* disk interlace chart */
0, 64, 57, 121, 50, 114, 43, 107, 36, 100, 29, 93, 22, 86, 15, 79, 8, 72,
1, 65, 58, 122, 51, 115, 44, 108, 37, 101, 30, 94, 23, 87, 16, 80, 9, 73,
2, 66, 59, 123, 52, 116, 45, 109, 38, 102, 31, 95, 24, 88, 17, 81, 10, 74,
3, 67, 60, 124, 53, 117, 46, 110, 39, 103, 32, 96, 25, 89, 18, 82, 11, 75,
4, 68, 61, 125, 54, 118, 47, 111, 40, 104, 33, 97, 26, 90, 19, 83, 12, 76,
5, 69, 62, 126, 55, 119, 48, 112, 41, 105, 34, 98, 27, 91, 20, 84, 12, 77,
6, 70, 63, 127, 56, 120, 49, 113, 42, 106, 35, 99, 28, 92, 21, 85, 13, 78,
7, 71
};
static const uint32 log_to_phys_21[NSC_21] = { /* disk interlace chart */
0, 64, 57, 121, 50, 114, 43, 107, 36, 100, 29, 93, 22, 86, 15, 79, 8, 72,
1, 65, 58, 122, 51, 115, 44, 108, 37, 101, 30, 94, 23, 87, 16, 80, 9, 73,
2, 66, 59, 123, 52, 116, 45, 109, 38, 102, 31, 95, 24, 88, 17, 81, 10, 74,
3, 67, 60, 124, 53, 117, 46, 110, 39, 103, 32, 96, 25, 89, 18, 82, 11, 75,
4, 68, 61, 125, 54, 118, 47, 111, 40, 104, 33, 97, 26, 90, 19, 83, 12, 76,
5, 69, 62, 126, 55, 119, 48, 112, 41, 105, 34, 98, 27, 91, 20, 84, 12, 77,
6, 70, 63, 127, 56, 120, 49, 113, 42, 106, 35, 99, 28, 92, 21, 85, 13, 78,
7, 71 };
t_stat sim_instr (void)
{
t_stat r = 0;
@@ -265,46 +274,53 @@ uint32 oPC;
/* Restore register state */
PC = PC & AMASK; /* mask PC */
sim_cancel_step (); /* defang SCP step */
if (lgp21_sov) { /* stop sense pending? */
lgp21_sov = 0;
if (!OVF) PC = (PC + 1) & AMASK; /* ovf off? skip */
else OVF = 0; } /* on? reset */
PC = PC & AMASK; /* mask PC */
sim_cancel_step (); /* defang SCP step */
if (lgp21_sov) { /* stop sense pending? */
lgp21_sov = 0;
if (!OVF) PC = (PC + 1) & AMASK; /* ovf off? skip */
else OVF = 0; /* on? reset */
}
/* Main instruction fetch/decode loop */
do { if (sim_interval <= 0) { /* check clock queue */
if (r = sim_process_event ()) break; }
do {
if (sim_interval <= 0) { /* check clock queue */
if (r = sim_process_event ()) break;
}
if (delay > 0) { /* delay to next instr */
delay = delay - 1; /* count down delay */
sim_interval = sim_interval - 1;
continue; } /* skip execution */
if (delay > 0) { /* delay to next instr */
delay = delay - 1; /* count down delay */
sim_interval = sim_interval - 1;
continue; /* skip execution */
}
if (sim_brk_summ && /* breakpoint? */
sim_brk_test (PC, SWMASK ('E'))) {
r = STOP_IBKPT; /* stop simulation */
break; }
if (sim_brk_summ && /* breakpoint? */
sim_brk_test (PC, SWMASK ('E'))) {
r = STOP_IBKPT; /* stop simulation */
break;
}
IR = Read (oPC = PC); /* get instruction */
PC = (PC + 1) & AMASK; /* increment PC */
sim_interval = sim_interval - 1;
IR = Read (oPC = PC); /* get instruction */
PC = (PC + 1) & AMASK; /* increment PC */
sim_interval = sim_interval - 1;
if (r = cpu_one_inst (oPC, IR)) { /* one instr; error? */
if (r == STOP_STALL) { /* stall? */
PC = oPC; /* back up PC */
delay = r = 0; } /* no delay */
else break; }
if (r = cpu_one_inst (oPC, IR)) { /* one instr; error? */
if (r == STOP_STALL) { /* stall? */
PC = oPC; /* back up PC */
delay = r = 0; /* no delay */
}
else break;
}
if (sim_step && (--sim_step <= 0)) /* do step count */
r = SCPE_STOP;
if (sim_step && (--sim_step <= 0)) /* do step count */
r = SCPE_STOP;
} while (r == 0); /* loop until halted */
pcq_r->qptr = pcq_p; /* update pc q ptr */
} while (r == 0); /* loop until halted */
pcq_r->qptr = pcq_p; /* update pc q ptr */
return r;
}
/* Execute one instruction */
t_stat cpu_one_inst (uint32 opc, uint32 ir)
@@ -313,160 +329,171 @@ uint32 ea, op, dat, res, dev, sh4, ch;
t_bool ovf_this_cycle = FALSE;
t_stat reason = 0;
op = I_GETOP (ir); /* opcode */
ea = I_GETEA (ir); /* address */
switch (op) { /* case on opcode */
op = I_GETOP (ir); /* opcode */
ea = I_GETEA (ir); /* address */
switch (op) { /* case on opcode */
/* Loads, stores, transfers instructions */
case OP_B: /* bring */
A = Read (ea); /* A <- M[ea] */
delay = I_delay (opc, ea, op);
break;
case OP_B: /* bring */
A = Read (ea); /* A <- M[ea] */
delay = I_delay (opc, ea, op);
break;
case OP_H: /* hold */
Write (ea, A); /* M[ea] <- A */
delay = I_delay (opc, ea, op);
break;
case OP_H: /* hold */
Write (ea, A); /* M[ea] <- A */
delay = I_delay (opc, ea, op);
break;
case OP_C: /* clear */
Write (ea, A); /* M[ea] <- A */
A = 0; /* A <- 0 */
delay = I_delay (opc, ea, op);
break;
case OP_C: /* clear */
Write (ea, A); /* M[ea] <- A */
A = 0; /* A <- 0 */
delay = I_delay (opc, ea, op);
break;
case OP_Y: /* store address */
dat = Read (ea); /* get operand */
dat = (dat & ~I_EA) | (A & I_EA); /* merge address */
Write (ea, dat);
delay = I_delay (opc, ea, op);
break;
case OP_Y: /* store address */
dat = Read (ea); /* get operand */
dat = (dat & ~I_EA) | (A & I_EA); /* merge address */
Write (ea, dat);
delay = I_delay (opc, ea, op);
break;
case OP_R: /* return address */
dat = Read (ea); /* get operand */
dat = (dat & ~I_EA) | (((PC + 1) & AMASK) << I_V_EA);
Write (ea, dat);
delay = I_delay (opc, ea, op);
break;
case OP_R: /* return address */
dat = Read (ea); /* get operand */
dat = (dat & ~I_EA) | (((PC + 1) & AMASK) << I_V_EA);
Write (ea, dat);
delay = I_delay (opc, ea, op);
break;
case OP_U: /* uncond transfer */
PCQ_ENTRY;
PC = ea; /* transfer */
delay = I_delay (opc, ea, op);
break;
case OP_U: /* uncond transfer */
PCQ_ENTRY;
PC = ea; /* transfer */
delay = I_delay (opc, ea, op);
break;
case OP_T: /* conditional transfer */
if ((A & SIGN) || /* A < 0 or */
((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */
PCQ_ENTRY;
PC = ea; /* transfer */
}
delay = I_delay (opc, ea, op);
break;
case OP_T: /* conditional transfer */
if ((A & SIGN) || /* A < 0 or */
((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */
PCQ_ENTRY;
PC = ea; } /* transfer */
delay = I_delay (opc, ea, op);
break;
/* Arithmetic and logical instructions */
case OP_A: /* add */
dat = Read (ea); /* get operand */
res = (A + dat) & DMASK; /* add */
if ((~A ^ dat) & (dat ^ res) & SIGN) /* calc overflow */
ovf_this_cycle = TRUE;
A = res; /* save result */
delay = I_delay (opc, ea, op);
break;
case OP_A: /* add */
dat = Read (ea); /* get operand */
res = (A + dat) & DMASK; /* add */
if ((~A ^ dat) & (dat ^ res) & SIGN) /* calc overflow */
ovf_this_cycle = TRUE;
A = res; /* save result */
delay = I_delay (opc, ea, op);
break;
case OP_S: /* sub */
dat = Read (ea); /* get operand */
res = (A - dat) & DMASK; /* subtract */
if ((A ^ dat) & (~dat ^ res) & SIGN) /* calc overflow */
ovf_this_cycle = TRUE;
A = res;
delay = I_delay (opc, ea, op);
break;
case OP_S: /* sub */
dat = Read (ea); /* get operand */
res = (A - dat) & DMASK; /* subtract */
if ((A ^ dat) & (~dat ^ res) & SIGN) /* calc overflow */
ovf_this_cycle = TRUE;
A = res;
delay = I_delay (opc, ea, op);
break;
case OP_M: /* multiply high */
dat = Read (ea); /* get operand */
A = (Mul64 (A, dat, NULL) << 1) & DMASK; /* multiply */
delay = I_delay (opc, ea, op);
break;
case OP_M: /* multiply high */
dat = Read (ea); /* get operand */
A = (Mul64 (A, dat, NULL) << 1) & DMASK; /* multiply */
delay = I_delay (opc, ea, op);
break;
case OP_N: /* multiply low */
dat = Read (ea); /* get operand */
Mul64 (A, dat, &res); /* multiply */
A = res; /* keep low result */
delay = I_delay (opc, ea, op); /* total delay */
break;
case OP_N: /* multiply low */
dat = Read (ea); /* get operand */
Mul64 (A, dat, &res); /* multiply */
A = res; /* keep low result */
delay = I_delay (opc, ea, op); /* total delay */
break;
case OP_D: /* divide */
dat = Read (ea); /* get operand */
if (Div32 (A, dat, &A)) ovf_this_cycle = TRUE; /* divide; overflow? */
delay = I_delay (opc, ea, op);
break;
case OP_D: /* divide */
dat = Read (ea); /* get operand */
if (Div32 (A, dat, &A)) ovf_this_cycle = TRUE; /* divide; overflow? */
delay = I_delay (opc, ea, op);
break;
case OP_E: /* extract */
dat = Read (ea); /* get operand */
A = A & dat; /* and */
delay = I_delay (opc, ea, op);
break;
case OP_E: /* extract */
dat = Read (ea); /* get operand */
A = A & dat; /* and */
delay = I_delay (opc, ea, op);
break;
/* IO instructions */
case OP_P: /* output */
if (Q_LGP21) { /* LGP-21 */
ch = A >> 26; /* char, 6b */
if (ir & SIGN) ch = (ch & 0x3C) | 2; /* 4b? convert */
dev = I_GETTK (ir); } /* device select */
else { /* LGP-30 */
ch = I_GETTK (ir); /* char, always 6b */
dev = Q_OUTPT? DEV_PT: DEV_TT; } /* device select */
reason = op_p (dev & DEV_MASK, ch); /* output */
delay = I_delay (sim_grtime (), ea, op); /* next instruction */
break;
case OP_P: /* output */
if (Q_LGP21) { /* LGP-21 */
ch = A >> 26; /* char, 6b */
if (ir & SIGN) ch = (ch & 0x3C) | 2; /* 4b? convert */
dev = I_GETTK (ir); /* device select */
}
else { /* LGP-30 */
ch = I_GETTK (ir); /* char, always 6b */
dev = Q_OUTPT? DEV_PT: DEV_TT; /* device select */
}
reason = op_p (dev & DEV_MASK, ch); /* output */
delay = I_delay (sim_grtime (), ea, op); /* next instruction */
break;
case OP_I: /* input */
if (Q_LGP21) { /* LGP-21 */
ch = 0; /* initial shift */
sh4 = ir & SIGN; /* 4b/6b select */
dev = I_GETTK (ir); } /* device select */
else { /* LGP-30 */
ch = I_GETTK (ir); /* initial shift */
sh4 = Q_IN4B; /* 4b/6b select */
dev = Q_INPT? DEV_PT: DEV_TT; } /* device select */
if (dev == DEV_SHIFT) /* shift? */
A = shift_in (A, 0, sh4); /* shift 4/6b */
else reason = op_i (dev & DEV_MASK, ch, sh4); /* input */
delay = I_delay (sim_grtime (), ea, op); /* next instruction */
break;
case OP_I: /* input */
if (Q_LGP21) { /* LGP-21 */
ch = 0; /* initial shift */
sh4 = ir & SIGN; /* 4b/6b select */
dev = I_GETTK (ir); /* device select */
}
else { /* LGP-30 */
ch = I_GETTK (ir); /* initial shift */
sh4 = Q_IN4B; /* 4b/6b select */
dev = Q_INPT? DEV_PT: DEV_TT; /* device select */
}
if (dev == DEV_SHIFT) /* shift? */
A = shift_in (A, 0, sh4); /* shift 4/6b */
else reason = op_i (dev & DEV_MASK, ch, sh4); /* input */
delay = I_delay (sim_grtime (), ea, op); /* next instruction */
break;
case OP_Z:
if (Q_LGP21) { /* LGP-21 */
if (ea & 0xF80) { /* no stop? */
if (((ea & 0x800) && !bp32) || /* skip if any */
((ea & 0x400) && !bp16) || /* selected switch */
((ea & 0x200) && !bp8) || /* is off */
((ea & 0x100) && !bp4) || /* or if */
((ir & SIGN) && !OVF)) /* ovf sel and off */
PC = (PC + 1) & AMASK;
if (ir & SIGN) OVF = 0; } /* -Z? clr overflow */
else { /* stop */
lgp21_sov = (ir & SIGN)? 1: 0; /* pending sense? */
reason = STOP_STOP; } } /* stop */
else { /* LGP-30 */
if (out_done) out_done = 0; /* P complete? */
else if (((ea & 0x800) && bp32) || /* bpt switch set? */
((ea & 0x400) && bp16) ||
((ea & 0x200) && bp8) ||
((ea & 0x100) && bp4)) ; /* don't stop or stall */
else if (out_strt) reason = STOP_STALL; /* P pending? stall */
else reason = STOP_STOP; } /* no, stop */
delay = I_delay (sim_grtime (), ea, op); /* next instruction */
break; } /* end switch */
case OP_Z:
if (Q_LGP21) { /* LGP-21 */
if (ea & 0xF80) { /* no stop? */
if (((ea & 0x800) && !bp32) || /* skip if any */
((ea & 0x400) && !bp16) || /* selected switch */
((ea & 0x200) && !bp8) || /* is off */
((ea & 0x100) && !bp4) || /* or if */
((ir & SIGN) && !OVF)) /* ovf sel and off */
PC = (PC + 1) & AMASK;
if (ir & SIGN) OVF = 0; /* -Z? clr overflow */
}
else { /* stop */
lgp21_sov = (ir & SIGN)? 1: 0; /* pending sense? */
reason = STOP_STOP; /* stop */
}
}
else { /* LGP-30 */
if (out_done) out_done = 0; /* P complete? */
else if (((ea & 0x800) && bp32) || /* bpt switch set? */
((ea & 0x400) && bp16) ||
((ea & 0x200) && bp8) ||
((ea & 0x100) && bp4)) ; /* don't stop or stall */
else if (out_strt) reason = STOP_STALL; /* P pending? stall */
else reason = STOP_STOP; /* no, stop */
}
delay = I_delay (sim_grtime (), ea, op); /* next instruction */
break; /* end switch */
}
if (ovf_this_cycle) {
if (Q_LGP21) OVF = 1; /* LGP-21? set OVF */
else reason = STOP_OVF; } /* LGP-30? stop */
if (Q_LGP21) OVF = 1; /* LGP-21? set OVF */
else reason = STOP_OVF; /* LGP-30? stop */
}
return reason;
}
/* Support routines */
uint32 Read (uint32 ea)
@@ -495,28 +522,30 @@ uint32 Mul64 (uint32 a, uint32 b, uint32 *low)
uint32 sgn = a ^ b;
uint32 ah, bh, al, bl, rhi, rlo, rmid1, rmid2;
if ((a == 0) || (b == 0)) { /* zero argument? */
if (low) *low = 0;
return 0; }
if ((a == 0) || (b == 0)) { /* zero argument? */
if (low) *low = 0;
return 0;
}
a = ABS (a);
b = ABS (b);
ah = (a >> 16) & M16; /* split operands */
bh = (b >> 16) & M16; /* into 16b chunks */
ah = (a >> 16) & M16; /* split operands */
bh = (b >> 16) & M16; /* into 16b chunks */
al = a & M16;
bl = b & M16;
rhi = ah * bh; /* high result */
rhi = ah * bh; /* high result */
rmid1 = ah * bl;
rmid2 = al * bh;
rlo = al * bl;
rhi = rhi + ((rmid1 >> 16) & M16) + ((rmid2 >> 16) & M16);
rmid1 = (rlo + (rmid1 << 16)) & M32; /* add mid1 to lo */
if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */
rmid2 = (rmid1 + (rmid2 << 16)) & M32; /* add mid2 to to */
if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */
if (sgn & SIGN) { /* result negative? */
rmid2 = NEG (rmid2); /* negate */
rhi = (~rhi + (rmid2 == 0)) & M32; }
if (low) *low = rmid2; /* low result */
rmid1 = (rlo + (rmid1 << 16)) & M32; /* add mid1 to lo */
if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */
rmid2 = (rmid1 + (rmid2 << 16)) & M32; /* add mid2 to to */
if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */
if (sgn & SIGN) { /* result negative? */
rmid2 = NEG (rmid2); /* negate */
rhi = (~rhi + (rmid2 == 0)) & M32;
}
if (low) *low = rmid2; /* low result */
return rhi & M32;
}
@@ -530,16 +559,18 @@ uint32 i, quo;
dvd = ABS (dvd);
dvr = ABS (dvr);
if (dvd >= dvr) return TRUE;
for (i = quo = 0; i < 31; i++) { /* 31 iterations */
quo = quo << 1; /* shift quotient */
dvd = dvd << 1; /* shift dividend */
if (dvd >= dvr) { /* step work? */
dvd = (dvd - dvr) & M32; /* subtract dvr */
quo = quo + 1; } }
quo = (quo + 1) & MMASK; /* round low bit */
if (sgn & SIGN) quo = NEG (quo); /* result -? */
if (q) *q = quo; /* return quo */
return FALSE; /* no overflow */
for (i = quo = 0; i < 31; i++) { /* 31 iterations */
quo = quo << 1; /* shift quotient */
dvd = dvd << 1; /* shift dividend */
if (dvd >= dvr) { /* step work? */
dvd = (dvd - dvr) & M32; /* subtract dvr */
quo = quo + 1;
}
}
quo = (quo + 1) & MMASK; /* round low bit */
if (sgn & SIGN) quo = NEG (quo); /* result -? */
if (q) *q = quo; /* return quo */
return FALSE; /* no overflow */
}
/* Rotational delay */
@@ -550,26 +581,30 @@ uint32 tmin = Q_LGP21? min_21[op]: min_30[op];
uint32 tmax = Q_LGP21? max_21[op]: max_30[op];
uint32 nsc, curp, newp, oprp, pcdelta, opdelta;
if (Q_LGP21) { /* LGP21 */
nsc = NSC_21; /* full rotation delay */
curp = log_to_phys_21[opc & SCMASK_21]; /* current phys pos */
newp = log_to_phys_21[PC & SCMASK_21]; /* new PC phys pos */
oprp = log_to_phys_21[ea & SCMASK_21]; /* ea phys pos */
pcdelta = (newp - curp + NSC_21) & SCMASK_21;
opdelta = (oprp - curp + NSC_21) & SCMASK_21; }
else { nsc = NSC_30;
curp = log_to_phys_30[opc & SCMASK_30];
newp = log_to_phys_30[PC & SCMASK_30];
oprp = log_to_phys_30[ea & SCMASK_30];
pcdelta = (newp - curp + NSC_30) & SCMASK_30;
opdelta = (oprp - curp + NSC_30) & SCMASK_30; }
if (tmax == 0) { /* skip ea calc? */
if (pcdelta >= tmin) return pcdelta - 1; /* new PC >= min? */
return pcdelta + nsc - 1; }
if (Q_LGP21) { /* LGP21 */
nsc = NSC_21; /* full rotation delay */
curp = log_to_phys_21[opc & SCMASK_21]; /* current phys pos */
newp = log_to_phys_21[PC & SCMASK_21]; /* new PC phys pos */
oprp = log_to_phys_21[ea & SCMASK_21]; /* ea phys pos */
pcdelta = (newp - curp + NSC_21) & SCMASK_21;
opdelta = (oprp - curp + NSC_21) & SCMASK_21;
}
else {
nsc = NSC_30;
curp = log_to_phys_30[opc & SCMASK_30];
newp = log_to_phys_30[PC & SCMASK_30];
oprp = log_to_phys_30[ea & SCMASK_30];
pcdelta = (newp - curp + NSC_30) & SCMASK_30;
opdelta = (oprp - curp + NSC_30) & SCMASK_30;
}
if (tmax == 0) { /* skip ea calc? */
if (pcdelta >= tmin) return pcdelta - 1; /* new PC >= min? */
return pcdelta + nsc - 1;
}
if ((opdelta >= tmin) && (opdelta <= tmax)) return pcdelta - 1;
return pcdelta + nsc - 1;
}
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
@@ -636,9 +671,10 @@ if (uptr->flags & UNIT_TTSS_D) fputs (", track/sector", st);
if (uptr->flags & UNIT_LGPH_D) fputs (", LGP hex", st);
fputs (Q_MANI? ", manual": ", tape", st);
if (!Q_LGP21) {
fputs (Q_IN4B? ", 4b": ", 6b", st);
fputs (Q_INPT? ", in=PTR": ", in=TTI", st);
fputs (Q_OUTPT? ", out=PTP": ", out=TTO", st); }
fputs (Q_IN4B? ", 4b": ", 6b", st);
fputs (Q_INPT? ", in=PTR": ", in=TTI", st);
fputs (Q_OUTPT? ", out=PTP": ", out=TTO", st);
}
return SCPE_OK;
}
@@ -668,12 +704,14 @@ uint32 inst;
t_stat r;
if (cptr) {
inst = get_uint (cptr, 16, DMASK, &r);
if (r != SCPE_OK) r; }
inst = get_uint (cptr, 16, DMASK, &r);
if (r != SCPE_OK) return r;
}
else inst = IR;
while ((r = cpu_one_inst (PC, inst)) == STOP_STALL) {
sim_interval = 0;
if (r = sim_process_event ()) return r; }
sim_interval = 0;
if (r = sim_process_event ()) return r;
}
return r;
}
@@ -685,9 +723,10 @@ uint32 inst;
t_stat r;
if (cptr) {
inst = get_uint (cptr, 16, DMASK, &r);
if (r != SCPE_OK) r;
IR = inst; }
inst = get_uint (cptr, 16, DMASK, &r);
if (r != SCPE_OK) return r;
IR = inst;
}
else IR = A;
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* lgp_defs.h: LGP simulator definitions
Copyright (c) 2004, Robert M. Supnik
Copyright (c) 2004-2005, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -19,112 +19,113 @@
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 Robert M Supnik shall not
Except as contained in this notice, the name of Robert M Supnik shall not be
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
*/
#ifndef _LGP_DEFS_H_
#define _LGP_DEFS_H_ 0
#define _LGP_DEFS_H_ 0
#include "sim_defs.h" /* simulator defns */
#include "sim_defs.h" /* simulator defns */
/* Simulator stop codes */
#define STOP_STOP 1 /* STOP */
#define STOP_IBKPT 2 /* breakpoint */
#define STOP_OVF 3 /* overflow */
#define STOP_NXDEV 4 /* non-existent device */
#define STOP_STALL 5 /* IO stall */
#define STOP_STOP 1 /* STOP */
#define STOP_IBKPT 2 /* breakpoint */
#define STOP_OVF 3 /* overflow */
#define STOP_NXDEV 4 /* non-existent device */
#define STOP_STALL 5 /* IO stall */
/* Memory */
#define MEMSIZE 4096 /* memory size */
#define AMASK 0xFFF /* addr mask */
#define NTK_30 64
#define NSC_30 64
#define SCMASK_30 0x03F /* sector mask */
#define NTK_21 32
#define NSC_21 128
#define SCMASK_21 0x07F
#define RPM 4000 /* rev/minutes */
#define WPS ((NSC_30 * RPM) / 60) /* words/second */
#define MEMSIZE 4096 /* memory size */
#define AMASK 0xFFF /* addr mask */
#define NTK_30 64
#define NSC_30 64
#define SCMASK_30 0x03F /* sector mask */
#define NTK_21 32
#define NSC_21 128
#define SCMASK_21 0x07F
#define RPM 4000 /* rev/minutes */
#define WPS ((NSC_30 * RPM) / 60) /* words/second */
/* Architectural constants */
#define SIGN 0x80000000 /* sign */
#define DMASK 0xFFFFFFFF /* data mask */
#define MMASK 0xFFFFFFFE /* memory mask */
#define SIGN 0x80000000 /* sign */
#define DMASK 0xFFFFFFFF /* data mask */
#define MMASK 0xFFFFFFFE /* memory mask */
/* Instruction format */
#define I_M_OP 0xF /* opcode */
#define I_V_OP 16
#define I_OP (I_M_OP << I_V_OP)
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
#define I_M_EA AMASK /* address */
#define I_V_EA 2
#define I_EA (I_M_EA << I_V_EA)
#define I_GETEA(x) (((x) >> I_V_EA) & I_M_EA)
#define I_M_TK 0x3F /* LGP-30 char */
#define I_V_TK 8 /* LGP-21 device */
#define I_GETTK(x) (((x) >> I_V_TK) & I_M_TK)
#define I_M_OP 0xF /* opcode */
#define I_V_OP 16
#define I_OP (I_M_OP << I_V_OP)
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
#define I_M_EA AMASK /* address */
#define I_V_EA 2
#define I_EA (I_M_EA << I_V_EA)
#define I_GETEA(x) (((x) >> I_V_EA) & I_M_EA)
#define I_M_TK 0x3F /* LGP-30 char */
#define I_V_TK 8 /* LGP-21 device */
#define I_GETTK(x) (((x) >> I_V_TK) & I_M_TK)
/* Unit flags */
#define UNIT_V_LGP21 (UNIT_V_UF + 0)
#define UNIT_V_MANI (UNIT_V_UF + 1)
#define UNIT_V_INPT (UNIT_V_UF + 2)
#define UNIT_V_OUTPT (UNIT_V_UF + 3)
#define UNIT_V_IN4B (UNIT_V_UF + 4)
#define UNIT_V_TTSS_D (UNIT_V_UF + 5)
#define UNIT_V_LGPH_D (UNIT_V_UF + 6)
#define UNIT_V_FLEX_D (UNIT_V_UF + 7) /* Flex default */
#define UNIT_V_FLEX (UNIT_V_UF + 8) /* Flex format */
#define UNIT_V_NOCS (UNIT_V_UF + 9) /* ignore cond stop */
#define UNIT_LGP21 (1u << UNIT_V_LGP21)
#define UNIT_MANI (1u << UNIT_V_MANI)
#define UNIT_INPT (1u << UNIT_V_INPT)
#define UNIT_OUTPT (1u << UNIT_V_OUTPT)
#define UNIT_IN4B (1u << UNIT_V_IN4B)
#define UNIT_TTSS_D (1u << UNIT_V_TTSS_D)
#define UNIT_LGPH_D (1u << UNIT_V_LGPH_D)
#define UNIT_FLEX_D (1u << UNIT_V_FLEX_D)
#define UNIT_FLEX (1u << UNIT_V_FLEX)
#define UNIT_NOCS (1u << UNIT_V_NOCS)
#define Q_LGP21 (cpu_unit.flags & UNIT_LGP21)
#define Q_MANI (cpu_unit.flags & UNIT_MANI)
#define Q_INPT (cpu_unit.flags & UNIT_INPT)
#define Q_OUTPT (cpu_unit.flags & UNIT_OUTPT)
#define Q_IN4B (cpu_unit.flags & UNIT_IN4B)
#define UNIT_V_LGP21 (UNIT_V_UF + 0)
#define UNIT_V_MANI (UNIT_V_UF + 1)
#define UNIT_V_INPT (UNIT_V_UF + 2)
#define UNIT_V_OUTPT (UNIT_V_UF + 3)
#define UNIT_V_IN4B (UNIT_V_UF + 4)
#define UNIT_V_TTSS_D (UNIT_V_UF + 5)
#define UNIT_V_LGPH_D (UNIT_V_UF + 6)
#define UNIT_V_FLEX_D (UNIT_V_UF + 7) /* Flex default */
#define UNIT_V_FLEX (UNIT_V_UF + 8) /* Flex format */
#define UNIT_V_NOCS (UNIT_V_UF + 9) /* ignore cond stop */
#define UNIT_LGP21 (1u << UNIT_V_LGP21)
#define UNIT_MANI (1u << UNIT_V_MANI)
#define UNIT_INPT (1u << UNIT_V_INPT)
#define UNIT_OUTPT (1u << UNIT_V_OUTPT)
#define UNIT_IN4B (1u << UNIT_V_IN4B)
#define UNIT_TTSS_D (1u << UNIT_V_TTSS_D)
#define UNIT_LGPH_D (1u << UNIT_V_LGPH_D)
#define UNIT_FLEX_D (1u << UNIT_V_FLEX_D)
#define UNIT_FLEX (1u << UNIT_V_FLEX)
#define UNIT_NOCS (1u << UNIT_V_NOCS)
#define Q_LGP21 (cpu_unit.flags & UNIT_LGP21)
#define Q_MANI (cpu_unit.flags & UNIT_MANI)
#define Q_INPT (cpu_unit.flags & UNIT_INPT)
#define Q_OUTPT (cpu_unit.flags & UNIT_OUTPT)
#define Q_IN4B (cpu_unit.flags & UNIT_IN4B)
/* IO return */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
/* Significant characters */
#define FLEX_LC 0x04
#define FLEX_UC 0x08
#define FLEX_CR 0x10
#define FLEX_BS 0x14
#define FLEX_CSTOP 0x20
#define FLEX_DEL 0x3F
#define FLEX_LC 0x04
#define FLEX_UC 0x08
#define FLEX_CR 0x10
#define FLEX_BS 0x14
#define FLEX_CSTOP 0x20
#define FLEX_DEL 0x3F
/* LGP-21 device assignments */
#define DEV_PT 0
#define DEV_TT 2
#define DEV_MASK 0x1F
#define DEV_SHIFT 62
#define DEV_PT 0
#define DEV_TT 2
#define DEV_MASK 0x1F
#define DEV_SHIFT 62
/* Instructions */
enum opcodes {
OP_Z, OP_B, OP_Y, OP_R,
OP_I, OP_D, OP_N, OP_M,
OP_P, OP_E, OP_U, OP_T,
OP_H, OP_C, OP_A, OP_S };
OP_Z, OP_B, OP_Y, OP_R,
OP_I, OP_D, OP_N, OP_M,
OP_P, OP_E, OP_U, OP_T,
OP_H, OP_C, OP_A, OP_S
};
/* Prototypes */

View File

@@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary:
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 Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the GRI-909 simulator.

View File

@@ -1,6 +1,6 @@
/* lgp_stddev.c: LGP-30 standard devices
Copyright (c) 2004, Robert M Supnik
Copyright (c) 2004-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -19,14 +19,14 @@
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 Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
tti typewriter input (keyboard and reader)
tto typewriter output (printer and punch)
ptr high speed reader
ptpp high speed punch
tti typewriter input (keyboard and reader)
tto typewriter output (printer and punch)
ptr high speed reader
ptpp high speed punch
*/
#include "lgp_defs.h"
@@ -67,403 +67,457 @@ t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc);
extern uint32 shift_in (uint32 a, uint32 dat, uint32 sh4);
/* Conversion tables */
const int32 flex_to_ascii[128] = {
-1 , 'z', '0', ' ', '>', 'b', '1', '-',
'<' , 'y', '2', '+', '|', 'r', '3', ';',
'\r', 'i', '4', '/','\\', 'd', '5', '.',
'\t', 'n', '6', ',', -1 , 'm', '7', 'v',
'\'', 'p', '8', 'o', -1 , 'e', '9', 'x',
-1 , 'u', 'f', -1 , -1 , 't', 'g', -1 ,
-1 , 'h', 'j', -1 , -1 , 'c', 'k', -1 ,
-1 , 'a', 'q', -1 , -1 , 's', 'w', 0 ,
-1 , 'z', '0', ' ', '>', 'b', '1', '-',
'<' , 'y', '2', '+', '|', 'r', '3', ';',
'\r', 'i', '4', '/','\\', 'd', '5', '.',
'\t', 'n', '6', ',', -1 , 'm', '7', 'v',
'\'', 'p', '8', 'o', -1 , 'e', '9', 'x',
-1 , 'u', 'f', -1 , -1 , 't', 'g', -1 ,
-1 , 'h', 'j', -1 , -1 , 'c', 'k', -1 ,
-1 , 'a', 'q', -1 , -1 , 's', 'w', 0 ,
-1 , 'Z', ')', ' ', -1 , 'B', 'L', '_',
-1 , 'Y', '*', '=', '|', 'R', '"', ':',
'\r', 'I', '^', '?','\\', 'D', '%', ']',
'\t', 'N', '$', '[', -1 , 'M', '~', 'V',
'\'', 'P', '#', 'O', -1 , 'E', '(', 'X',
-1 , 'U', 'F', -1 , -1 , 'T', 'G', -1 ,
-1 , 'H', 'J', -1 , -1 , 'C', 'K', -1 ,
-1 , 'A', 'Q', -1 , -1 , 'S', 'W', 0 };
-1 , 'Z', ')', ' ', -1 , 'B', 'L', '_',
-1 , 'Y', '*', '=', '|', 'R', '"', ':',
'\r', 'I', '^', '?','\\', 'D', '%', ']',
'\t', 'N', '$', '[', -1 , 'M', '~', 'V',
'\'', 'P', '#', 'O', -1 , 'E', '(', 'X',
-1 , 'U', 'F', -1 , -1 , 'T', 'G', -1 ,
-1 , 'H', 'J', -1 , -1 , 'C', 'K', -1 ,
-1 , 'A', 'Q', -1 , -1 , 'S', 'W', 0
};
const int32 ascii_to_flex[128] = {
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
024, 030, -1 , -1 , -1 , 020, -1 , -1 ,
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
003, -1 , 016, 042, 032, 026, -1 , 040,
046, 001, 012, 013, 033, 007, 027, 023,
002, 006, 012, 016, 022, 026, 032, 036,
042, 046, 017, 017, 004, 013, 010, 023,
-1 , 071, 005, 065, 025, 045, 052, 056,
061, 021, 062, 066, 006, 035, 031, 043,
041, 072, 015, 075, 055, 051, 037, 076,
047, 011, 001, 033, -1 , 027, 022, 007,
- 1, 071, 005, 065, 025, 045, 052, 056,
061, 021, 062, 066, 006, 035, 031, 043,
041, 072, 015, 075, 055, 051, 037, 076,
047, 011, 001, -1 , 014, -1 , 036, 077 };
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
024, 030, -1 , -1 , -1 , 020, -1 , -1 ,
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
003, -1 , 016, 042, 032, 026, -1 , 040,
046, 001, 012, 013, 033, 007, 027, 023,
002, 006, 012, 016, 022, 026, 032, 036,
042, 046, 017, 017, 004, 013, 010, 023,
-1 , 071, 005, 065, 025, 045, 052, 056,
061, 021, 062, 066, 006, 035, 031, 043,
041, 072, 015, 075, 055, 051, 037, 076,
047, 011, 001, 033, -1 , 027, 022, 007,
- 1, 071, 005, 065, 025, 045, 052, 056,
061, 021, 062, 066, 006, 035, 031, 043,
041, 072, 015, 075, 055, 051, 037, 076,
047, 011, 001, -1 , 014, -1 , 036, 077
};
static const uint8 flex_inp_valid[64] = {
1, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1 };
1, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1
};
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit descriptor
tti_mod TTI modifier list
tti_reg TTI register list
tti_dev TTI device descriptor
tti_unit TTI unit descriptor
tti_mod TTI modifier list
tti_reg TTI register list
*/
UNIT tti_unit[] = {
{ UDATA (&tti_svc, 0, 0) },
{ UDATA (&ttr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) } };
{ UDATA (&tti_svc, 0, 0) },
{ UDATA (&ttr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }
};
REG tti_reg[] = {
{ HRDATA (BUF, tti_buf, 6) },
{ FLDATA (RDY, tti_rdy, 0) },
{ DRDATA (KPOS, tti_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (RPOS, tti_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tt_wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ttr_stopioe, 0) },
{ NULL } };
{ HRDATA (BUF, tti_buf, 6) },
{ FLDATA (RDY, tti_rdy, 0) },
{ DRDATA (KPOS, tti_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (RPOS, tti_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tt_wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ttr_stopioe, 0) },
{ NULL }
};
MTAB tti_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE+UNIT_NOCS,
"ignore conditional stop", "NOCSTOP", &tap_attable },
{ UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE ,
NULL, "CSTOP", &tap_attable },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "START", &send_start },
{ MTAB_XTD|MTAB_VDV, 1, NULL, "RSTART", &tti_rdrss },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "RSTOP", &tti_rdrss },
{ 0, 0 } };
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE+UNIT_NOCS,
"ignore conditional stop", "NOCSTOP", &tap_attable },
{ UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE ,
NULL, "CSTOP", &tap_attable },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "START", &send_start },
{ MTAB_XTD|MTAB_VDV, 1, NULL, "RSTART", &tti_rdrss },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "RSTOP", &tti_rdrss },
{ 0 }
};
DEVICE tti_dev = {
"TTI", tti_unit, tti_reg, tti_mod,
2, 10, 31, 1, 16, 7,
NULL, NULL, &tti_reset,
NULL, &tap_attach, NULL };
"TTI", tti_unit, tti_reg, tti_mod,
2, 10, 31, 1, 16, 7,
NULL, NULL, &tti_reset,
NULL, &tap_attach, NULL
};
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit descriptor
tto_mod TTO modifier list
tto_reg TTO register list
tto_dev TTO device descriptor
tto_unit TTO unit descriptor
tto_mod TTO modifier list
tto_reg TTO register list
*/
UNIT tto_unit[] = {
{ UDATA (&tto_svc, 0, 0) },
{ UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } };
{ UDATA (&tto_svc, 0, 0) },
{ UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }
};
REG tto_reg[] = {
{ HRDATA (BUF, tto_buf, 6) },
{ FLDATA (UC, tto_uc, 0) },
{ DRDATA (TPOS, tto_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (PPOS, tto_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tt_wait, 24), PV_LEFT },
{ NULL } };
{ HRDATA (BUF, tto_buf, 6) },
{ FLDATA (UC, tto_uc, 0) },
{ DRDATA (TPOS, tto_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (PPOS, tto_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tt_wait, 24), PV_LEFT },
{ NULL }
};
MTAB tto_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ MTAB_XTD|MTAB_VUN, 0, NULL, "FEED", &punch_feed },
{ 0, 0 } };
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ MTAB_XTD|MTAB_VUN, 0, NULL, "FEED", &punch_feed },
{ 0 }
};
DEVICE tto_dev = {
"TTO", tto_unit, tto_reg, tto_mod,
2, 10, 31, 1, 16, 7,
NULL, NULL, &tto_reset,
NULL, &tap_attach, NULL };
"TTO", tto_unit, tto_reg, tto_mod,
2, 10, 31, 1, 16, 7,
NULL, NULL, &tto_reset,
NULL, &tap_attach, NULL
};
/* PTR data structures
ptr_dev PTR device descriptor
ptr_unit PTR unit descriptor
ptr_mod PTR modifier list
ptr_reg PTR register list
ptr_dev PTR device descriptor
ptr_unit PTR unit descriptor
ptr_mod PTR modifier list
ptr_reg PTR register list
*/
UNIT ptr_unit = {
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), WPS / 200 };
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), WPS / 200
};
REG ptr_reg[] = {
{ HRDATA (BUF, ptr_unit.buf, 6) },
{ FLDATA (RDY, ptr_rdy, 0) },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL } };
{ HRDATA (BUF, ptr_unit.buf, 6) },
{ FLDATA (RDY, ptr_rdy, 0) },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL }
};
MTAB ptr_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ 0, 0 } };
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ 0 }
};
DEVICE ptr_dev = {
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 16, 7,
NULL, NULL, &ptr_reset,
NULL, &tap_attach, NULL };
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 16, 7,
NULL, NULL, &ptr_reset,
NULL, &tap_attach, NULL
};
/* PTP data structures
ptp_dev PTP device descriptor
ptp_unit PTP unit descriptor
ptp_mod PTP modifier list
ptp_reg PTP register list
ptp_dev PTP device descriptor
ptp_unit PTP unit descriptor
ptp_mod PTP modifier list
ptp_reg PTP register list
*/
UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), WPS / 20 };
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), WPS / 20
};
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL } };
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL }
};
MTAB ptp_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ 0, 0 } };
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ 0 }
};
DEVICE ptp_dev = {
"PTP", &ptp_unit, ptp_reg, ptp_mod,
1, 10, 31, 1, 16, 7,
NULL, NULL, &ptp_reset,
NULL, &tap_attach, NULL };
"PTP", &ptp_unit, ptp_reg, ptp_mod,
1, 10, 31, 1, 16, 7,
NULL, NULL, &ptp_reset,
NULL, &tap_attach, NULL
};
/* Input instruction */
void op_i_strt (uint32 dev)
{
switch (dev) { /* case on device */
case DEV_PT: /* ptr */
sim_activate (&ptr_unit, ptr_unit.wait); /* activate */
break;
case DEV_TT: /* tti/ttr */
if (Q_MANI) sim_putchar ('`'); /* manual input? */
else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */
break; }
switch (dev) { /* case on device */
case DEV_PT: /* ptr */
sim_activate (&ptr_unit, ptr_unit.wait); /* activate */
break;
case DEV_TT: /* tti/ttr */
if (Q_MANI) sim_putchar ('`'); /* manual input? */
else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */
break;
}
return;
}
}
t_stat op_i (uint32 dev, uint32 ch, uint32 sh4)
{
if (Q_LGP21 && out_strt) return STOP_STALL; /* LGP-21? must be idle */
if (!inp_strt) { /* input started? */
inp_strt = 1; /* no, set start */
inp_done = 0; /* clear done */
A = shift_in (A, ch, sh4);
tti_rdy = ptr_rdy = 0; /* no input */
if (Q_LGP21 || Q_INPT) op_i_strt (dev); } /* LGP-21 or PTR? start */
if (Q_LGP21 && out_strt) return STOP_STALL; /* LGP-21? must be idle */
if (!inp_strt) { /* input started? */
inp_strt = 1; /* no, set start */
inp_done = 0; /* clear done */
A = shift_in (A, ch, sh4);
tti_rdy = ptr_rdy = 0; /* no input */
if (Q_LGP21 || Q_INPT) op_i_strt (dev); /* LGP-21 or PTR? start */
}
switch (dev) { /* case on device */
switch (dev) { /* case on device */
case DEV_PT: /* ptr */
if (ptr_rdy) { /* char ready? */
ptr_rdy = 0; /* reset ready */
if ((ptr_unit.buf != FLEX_DEL) && /* ignore delete and */
(!Q_LGP21 || ((ptr_unit.buf & 3) == 2))) /* LGP-21 4b? zone != 2 */
A = shift_in (A, ptr_unit.buf, sh4); } /* shift data in */
break;
case DEV_TT: /* tti/ttr */
if (tti_rdy) { /* char ready? */
tti_rdy = 0; /* reset ready */
if ((tti_buf != FLEX_DEL) && /* ignore delete and */
(!Q_LGP21 || ((tti_buf & 3) != 0))) /* LGP-21 4b? zone == 0 */
A = shift_in (A, tti_buf, sh4); } /* shift data in */
break;
default: /* nx device */
return STOP_NXDEV; } /* return error */
case DEV_PT: /* ptr */
if (ptr_rdy) { /* char ready? */
ptr_rdy = 0; /* reset ready */
if ((ptr_unit.buf != FLEX_DEL) && /* ignore delete and */
(!Q_LGP21 || ((ptr_unit.buf & 3) == 2))) /* LGP-21 4b? zone != 2 */
A = shift_in (A, ptr_unit.buf, sh4); /* shift data in */
}
break;
if (inp_done) { /* done? */
inp_strt = inp_done = 0; /* clear start, done */
return SCPE_OK; } /* no stall */
return STOP_STALL; /* stall */
case DEV_TT: /* tti/ttr */
if (tti_rdy) { /* char ready? */
tti_rdy = 0; /* reset ready */
if ((tti_buf != FLEX_DEL) && /* ignore delete and */
(!Q_LGP21 || ((tti_buf & 3) != 0))) /* LGP-21 4b? zone == 0 */
A = shift_in (A, tti_buf, sh4); /* shift data in */
}
break;
default: /* nx device */
return STOP_NXDEV; /* return error */
}
if (inp_done) { /* done? */
inp_strt = inp_done = 0; /* clear start, done */
return SCPE_OK; /* no stall */
}
return STOP_STALL; /* stall */
}
/* Terminal keyboard unit service */
t_stat tti_svc (UNIT *uptr)
{
int32 c, flex;
sim_activate (uptr, tt_wait); /* continue poll */
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */
if (flex > 0) { /* it's a typewriter... */
write_tto (flex); /* always echos */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
write_punch (&tto_unit[1], tto_buf); } /* punch to ttp */
else write_tto ('\a'); /* don't echo bad */
if (Q_MANI && (flex > 0) && flex_inp_valid[flex]) { /* wanted, valid? */
if (flex == FLEX_CSTOP) inp_done = 1; /* conditional stop? */
else tti_rdy = 1; /* no, set ready */
tti_buf = flex; /* save char */
uptr->pos = uptr->pos + 1; }
sim_activate (uptr, tt_wait); /* continue poll */
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */
if (flex > 0) { /* it's a typewriter... */
write_tto (flex); /* always echos */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
write_punch (&tto_unit[1], tto_buf); /* punch to ttp */
}
else write_tto ('\a'); /* don't echo bad */
if (Q_MANI && (flex > 0) && flex_inp_valid[flex]) { /* wanted, valid? */
if (flex == FLEX_CSTOP) inp_done = 1; /* conditional stop? */
else tti_rdy = 1; /* no, set ready */
tti_buf = flex; /* save char */
uptr->pos = uptr->pos + 1;
}
return SCPE_OK;
}
/* Terminal reader unit service */
t_stat ttr_svc (UNIT *uptr)
{
t_stat r;
if (r = read_reader (uptr, ttr_stopioe, (int32 *) &tti_buf)) return r;
if (!(uptr->flags & UNIT_NOCS) && /* cstop enable? */
(tti_buf == FLEX_CSTOP)) inp_done = 1; /* cond stop? */
else { tti_rdy = 1; /* no, set ready */
sim_activate (uptr, tt_wait); } /* cont reading */
write_tto (tti_buf); /* echo to tto */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
return write_punch (&tto_unit[1], tti_buf); /* punch to ttp */
if (!(uptr->flags & UNIT_NOCS) && /* cstop enable? */
(tti_buf == FLEX_CSTOP)) inp_done = 1; /* cond stop? */
else {
tti_rdy = 1; /* no, set ready */
sim_activate (uptr, tt_wait); /* cont reading */
}
write_tto (tti_buf); /* echo to tto */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
return write_punch (&tto_unit[1], tti_buf); /* punch to ttp */
return SCPE_OK;
}
/* Paper tape reader unit service */
t_stat ptr_svc (UNIT *uptr)
{
t_stat r;
if (r = read_reader (uptr, ptr_stopioe, &uptr->buf)) return r;
if (uptr->buf == FLEX_CSTOP) inp_done = 1; /* cond stop? */
else { ptr_rdy = 1; /* no, set ready */
sim_activate (uptr, uptr->wait); } /* cont reading */
if (uptr->buf == FLEX_CSTOP) inp_done = 1; /* cond stop? */
else {
ptr_rdy = 1; /* no, set ready */
sim_activate (uptr, uptr->wait); /* cont reading */
}
return SCPE_OK;
}
/* Output instruction */
t_stat op_p (uint32 dev, uint32 ch)
{
switch (dev) { /* case on device */
case DEV_PT: /* paper tape punch */
if (sim_is_active (&ptp_unit)) /* busy? */
return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
ptp_unit.buf = ch; /* save char */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate ptp */
break;
case DEV_TT: /* typewriter */
if (ch == 0) { /* start input? */
if (!Q_LGP21 && !Q_INPT) /* ignore if LGP-21, ptr */
op_i_strt (DEV_TT); /* start tti */
return SCPE_OK; } /* no stall */
if (sim_is_active (&tto_unit[0])) /* busy? */
return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
tto_buf = ch; /* save char */
sim_activate (&tto_unit[0], tt_wait); /* activate tto */
break;
default: /* unknown */
return STOP_NXDEV; } /* return error */
switch (dev) { /* case on device */
if (out_strt == 0) { /* output started? */
out_strt = 1; /* flag start */
out_done = 0; } /* clear done */
return SCPE_OK; /* no stall */
case DEV_PT: /* paper tape punch */
if (sim_is_active (&ptp_unit)) /* busy? */
return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
ptp_unit.buf = ch; /* save char */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate ptp */
break;
case DEV_TT: /* typewriter */
if (ch == 0) { /* start input? */
if (!Q_LGP21 && !Q_INPT) /* ignore if LGP-21, ptr */
op_i_strt (DEV_TT); /* start tti */
return SCPE_OK; /* no stall */
}
if (sim_is_active (&tto_unit[0])) /* busy? */
return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
tto_buf = ch; /* save char */
sim_activate (&tto_unit[0], tt_wait); /* activate tto */
break;
default: /* unknown */
return STOP_NXDEV; /* return error */
}
if (out_strt == 0) { /* output started? */
out_strt = 1; /* flag start */
out_done = 0; /* clear done */
}
return SCPE_OK; /* no stall */
}
/* TTO unit service */
/* Terminal printer unit service */
t_stat tto_svc (UNIT *uptr)
{
t_stat r;
if ((r = write_tto (tto_buf)) != SCPE_OK) { /* output; error? */
sim_activate (uptr, tt_wait); /* try again */
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
if ((r = write_tto (tto_buf)) != SCPE_OK) { /* output; error? */
sim_activate (uptr, tt_wait); /* try again */
return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
}
out_strt = 0;
out_done = 1;
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
return write_punch (&tto_unit[1], tto_buf); /* punch to ttp */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
return write_punch (&tto_unit[1], tto_buf); /* punch to ttp */
return SCPE_OK;
}
/* PTP unit service */
/* Paper tape punch unit service */
t_stat ptp_svc (UNIT *uptr)
{
out_strt = 0;
out_done = 1;
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return IORETURN (ptp_stopioe, SCPE_UNATT); /* error */
return write_punch (uptr, uptr->buf); /* write to ptp */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return IORETURN (ptp_stopioe, SCPE_UNATT); /* error */
return write_punch (uptr, uptr->buf); /* write to ptp */
}
/* Utility routines */
t_stat read_reader (UNIT *uptr, int32 stop, int32 *fl)
{
int32 ch, flex;
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (stop, SCPE_UNATT);
do { if ((ch = getc (uptr->fileref)) == EOF) { /* read char */
if (feof (uptr->fileref)) { /* err or eof? */
if (stop) printf ("Reader end of file\n");
else return SCPE_OK; }
else perror ("Reader I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
if (uptr->flags & UNIT_FLEX) /* transposed flex? */
flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */
else if (ch == '#') { /* encoded? */
int32 d1 = getc (uptr->fileref); /* get 2 digits */
int32 d2 = getc (uptr->fileref);
if ((d1 == EOF) || (d2 == EOF)) { /* error? */
if (feof (uptr->fileref)) { /* eof? */
if (stop) printf ("Reader end of file\n");
else return SCPE_OK; }
else perror ("Reader I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
flex = (((d1 - '0') * 10) + (d2 - '0')) & 0x3F;
uptr->pos = uptr->pos + 2; }
else flex = ascii_to_flex[ch & 0x7F]; /* convert */
uptr->pos = uptr->pos + 1; }
while (flex < 0); /* until valid */
*fl = flex; /* return char */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (stop, SCPE_UNATT);
do {
if ((ch = getc (uptr->fileref)) == EOF) { /* read char */
if (feof (uptr->fileref)) { /* err or eof? */
if (stop) printf ("Reader end of file\n");
else return SCPE_OK;
}
else perror ("Reader I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
if (uptr->flags & UNIT_FLEX) /* transposed flex? */
flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */
else if (ch == '#') { /* encoded? */
int32 d1 = getc (uptr->fileref); /* get 2 digits */
int32 d2 = getc (uptr->fileref);
if ((d1 == EOF) || (d2 == EOF)) { /* error? */
if (feof (uptr->fileref)) { /* eof? */
if (stop) printf ("Reader end of file\n");
else return SCPE_OK;
}
else perror ("Reader I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
flex = (((d1 - '0') * 10) + (d2 - '0')) & 0x3F;
uptr->pos = uptr->pos + 2;
}
else flex = ascii_to_flex[ch & 0x7F]; /* convert */
uptr->pos = uptr->pos + 1;
} while (flex < 0); /* until valid */
*fl = flex; /* return char */
return SCPE_OK;
}
@@ -472,16 +526,20 @@ t_stat write_tto (int32 flex)
int32 ch;
t_stat r;
if (flex == FLEX_UC) tto_uc = 1; /* UC? set state */
else if (flex == FLEX_LC) tto_uc = 0; /* LC? set state */
else { if (flex == FLEX_BS) ch = '\b'; /* backspace? */
else ch = flex_to_ascii[flex | (tto_uc << 6)]; /* cvt flex to ascii */
if (ch > 0) { /* legit? */
if (r = sim_putchar_s (ch)) return r; /* write char */
tto_unit[0].pos = tto_unit[0].pos + 1;
if (flex == FLEX_CR) { /* cr? */
sim_putchar ('\n'); /* add lf */
tto_unit[0].pos = tto_unit[0].pos + 1; } } }
if (flex == FLEX_UC) tto_uc = 1; /* UC? set state */
else if (flex == FLEX_LC) tto_uc = 0; /* LC? set state */
else {
if (flex == FLEX_BS) ch = '\b'; /* backspace? */
else ch = flex_to_ascii[flex | (tto_uc << 6)]; /* cvt flex to ascii */
if (ch > 0) { /* legit? */
if (r = sim_putchar_s (ch)) return r; /* write char */
tto_unit[0].pos = tto_unit[0].pos + 1;
if (flex == FLEX_CR) { /* cr? */
sim_putchar ('\n'); /* add lf */
tto_unit[0].pos = tto_unit[0].pos + 1;
}
}
}
return SCPE_OK;
}
@@ -489,19 +547,20 @@ t_stat write_punch (UNIT *uptr, int32 flex)
{
int32 c, sta;
if (uptr->flags & UNIT_FLEX) /* transposed flex? */
c = ((flex >> 1) | (flex << 5)) & 0x3F; /* reorder to 612345 */
else c = flex_to_ascii[flex]; /* convert to ASCII */
if (c >= 0) sta = fputc (c, uptr->fileref); /* valid? */
else sta = fprintf (uptr->fileref, "#%02d", flex); /* no, encode */
if (sta == EOF) { /* error? */
perror ("Punch I/O error"); /* error? */
clearerr (uptr->fileref);
return SCPE_IOERR; }
uptr->pos = uptr->pos + ((c >= 0)? 1: 3); /* incr position */
if (uptr->flags & UNIT_FLEX) /* transposed flex? */
c = ((flex >> 1) | (flex << 5)) & 0x3F; /* reorder to 612345 */
else c = flex_to_ascii[flex]; /* convert to ASCII */
if (c >= 0) sta = fputc (c, uptr->fileref); /* valid? */
else sta = fprintf (uptr->fileref, "#%02d", flex); /* no, encode */
if (sta == EOF) { /* error? */
perror ("Punch I/O error"); /* error? */
clearerr (uptr->fileref);
return SCPE_IOERR;
}
uptr->pos = uptr->pos + ((c >= 0)? 1: 3); /* incr position */
return SCPE_OK;
}
/* Reset routines */
t_stat tti_reset (DEVICE *dptr)
@@ -545,7 +604,7 @@ t_stat r;
if ((r = attach_unit (uptr,cptr)) != SCPE_OK) return r;
if ((sim_switches & SWMASK ('F')) ||
((uptr->flags & UNIT_FLEX_D) && !(sim_switches & SWMASK ('A'))))
uptr->flags = uptr->flags | UNIT_FLEX;
uptr->flags = uptr->flags | UNIT_FLEX;
else uptr->flags = uptr->flags & ~UNIT_FLEX;
return SCPE_OK;
}
@@ -563,8 +622,9 @@ return SCPE_NOFNC;
t_stat tti_rdrss (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if (val) {
if ((tti_unit[1].flags & UNIT_ATT) == 0) return SCPE_UNATT;
sim_activate (&tti_unit[1], tt_wait); }
if ((tti_unit[1].flags & UNIT_ATT) == 0) return SCPE_UNATT;
sim_activate (&tti_unit[1], tt_wait);
}
else sim_cancel (&tti_unit[1]);
return SCPE_OK;
}
@@ -578,12 +638,14 @@ t_stat r;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
if (cptr) {
cnt = (int32) get_uint (cptr, 10, 512, &r);
if ((r != SCPE_OK) || (cnt == 0)) return SCPE_ARG; }
cnt = (int32) get_uint (cptr, 10, 512, &r);
if ((r != SCPE_OK) || (cnt == 0)) return SCPE_ARG;
}
else cnt = 10;
while (cnt-- > 0) {
r = write_punch (uptr, 0);
if (r != SCPE_OK) return r; }
r = write_punch (uptr, 0);
if (r != SCPE_OK) return r;
}
return SCPE_OK;
}

View File

@@ -19,11 +19,11 @@
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 Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
04-Jan-05 RMS Modified VM pointer setup
04-Jan-05 RMS Modified VM pointer setup
*/
#include "lgp_defs.h"
@@ -48,12 +48,12 @@ extern t_addr (*sim_vm_parse_addr) (DEVICE *dptr, char *cptr, char **tptr);
/* SCP data structures and interface routines
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
char sim_name[] = "LGP30";
@@ -63,34 +63,36 @@ REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&tti_dev,
&tto_dev,
&ptr_dev,
&ptp_dev,
NULL };
&cpu_dev,
&tti_dev,
&tto_dev,
&ptr_dev,
&ptp_dev,
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"STOP",
"Breakpoint",
"Arithmetic overflow" };
"Unknown error",
"STOP",
"Breakpoint",
"Arithmetic overflow"
};
/* Binary loader - implements a restricted form of subroutine 10.4
Switches:
-t, input file is transposed Flex
-n, no checksums on v commands (10.0 compatible)
default is ASCII encoded Flex
-t, input file is transposed Flex
-n, no checksums on v commands (10.0 compatible)
default is ASCII encoded Flex
Commands (in bits 0-3):
(blank) instruction
+ command (not supported)
; start fill
/ set modifier
. stop and transfer
, hex words
v hex fill (checksummed unless -n)
8 negative instruction
(blank) instruction
+ command (not supported)
; start fill
/ set modifier
. stop and transfer
, hex words
v hex fill (checksummed unless -n)
8 negative instruction
*/
/* Utility routine - read characters until ' (conditional stop) */
@@ -101,14 +103,15 @@ int32 flex, c;
*wd = 0;
while ((c = fgetc (fi)) != EOF) {
if (sim_switches & SWMASK ('T'))
flex = ((c << 1) | (c >> 5)) & 0x3F;
else flex = ascii_to_flex[c & 0x7F];
if ((flex == FLEX_CR) || (flex == FLEX_DEL) ||
(flex == FLEX_UC) || (flex == FLEX_LC) ||
(flex == FLEX_BS) || (flex < 0)) continue;
if (flex == FLEX_CSTOP) return SCPE_OK;
*wd = (*wd << 4) | ((flex >> 2) & 0xF); }
if (sim_switches & SWMASK ('T'))
flex = ((c << 1) | (c >> 5)) & 0x3F;
else flex = ascii_to_flex[c & 0x7F];
if ((flex == FLEX_CR) || (flex == FLEX_DEL) ||
(flex == FLEX_UC) || (flex == FLEX_LC) ||
(flex == FLEX_BS) || (flex < 0)) continue;
if (flex == FLEX_CSTOP) return SCPE_OK;
*wd = (*wd << 4) | ((flex >> 2) & 0xF);
}
return SCPE_FMT;
}
@@ -137,59 +140,70 @@ t_stat sim_load (FILE *fi, char *cptr, char *fnam, int flag)
uint32 wd, origin, amod, csum, cnt, tr, sc, ad, cmd;
origin = amod = 0;
for (;;) { /* until stopped */
if (load_getw (fi, &wd)) break; /* get ctrl word */
cmd = (wd >> 28) & 0xF; /* get <0:3> */
switch (cmd) { /* decode <0:3> */
case 0x2: /* + command */
return SCPE_FMT;
case 0x3: /* ; start fill */
if (load_geta (wd, &origin)) return SCPE_FMT; /* origin = addr */
break;
case 0x4: /* / set modifier */
if (load_geta (wd, &amod)) return SCPE_FMT; /* modifier = addr */
break;
case 0x5: /* . transfer */
if (load_geta (wd, &PC)) return SCPE_FMT; /* PC = addr */
return SCPE_OK; /* done! */
case 0x6: /* hex words */
if (load_geta (wd, &cnt)) return SCPE_FMT; /* count = addr */
if ((cnt == 0) || (cnt > 63)) return SCPE_FMT;
while (cnt--) { /* fill hex words */
if (load_getw (fi, &wd)) return SCPE_FMT;
Write (origin, wd);
origin = (origin + 1) & AMASK; }
break;
case 0x7: /* hex fill */
cnt = (wd >> 16) & 0xFFF; /* hex count */
tr = (wd >> 8) & 0xFF; /* hex track */
sc = wd & 0xFF; /* hex sector */
if ((cnt == 0) || (cnt > 0x7FF) || /* validate */
(tr >= NTK_30) || (sc >= NSC_30)) return SCPE_ARG;
ad = (tr * NSC_30) + sc; /* decimal addr */
for (csum = 0; cnt; cnt--) { /* fill words */
if (load_getw (fi, &wd)) return SCPE_FMT;
Write (ad, wd);
csum = (csum + wd) & MMASK;
ad = (ad + 1) & AMASK; }
if (!(sim_switches & SWMASK ('N'))) { /* unless -n, csum */
if (load_getw (fi, &wd)) return SCPE_FMT;
/* if ((csum ^wd) & MMASK) return SCPE_CSUM; */ }
break;
case 0x0: case 0x8: /* instructions */
if (load_geta (wd, &ad)) return SCPE_FMT; /* get address */
if ((wd & 0x00F00000) != 0x00900000) /* if not x, */
ad = (ad + amod) & AMASK; /* modify */
wd = (wd & (SIGN|I_OP)) + (ad << I_V_EA); /* instruction */
default: /* data word */
Write (origin, wd);
origin = (origin + 1) & AMASK;
break;
} /* end case */
} /* end for */
for (;;) { /* until stopped */
if (load_getw (fi, &wd)) break; /* get ctrl word */
cmd = (wd >> 28) & 0xF; /* get <0:3> */
switch (cmd) { /* decode <0:3> */
case 0x2: /* + command */
return SCPE_FMT;
case 0x3: /* ; start fill */
if (load_geta (wd, &origin)) return SCPE_FMT; /* origin = addr */
break;
case 0x4: /* / set modifier */
if (load_geta (wd, &amod)) return SCPE_FMT; /* modifier = addr */
break;
case 0x5: /* . transfer */
if (load_geta (wd, &PC)) return SCPE_FMT; /* PC = addr */
return SCPE_OK; /* done! */
case 0x6: /* hex words */
if (load_geta (wd, &cnt)) return SCPE_FMT; /* count = addr */
if ((cnt == 0) || (cnt > 63)) return SCPE_FMT;
while (cnt--) { /* fill hex words */
if (load_getw (fi, &wd)) return SCPE_FMT;
Write (origin, wd);
origin = (origin + 1) & AMASK;
}
break;
case 0x7: /* hex fill */
cnt = (wd >> 16) & 0xFFF; /* hex count */
tr = (wd >> 8) & 0xFF; /* hex track */
sc = wd & 0xFF; /* hex sector */
if ((cnt == 0) || (cnt > 0x7FF) || /* validate */
(tr >= NTK_30) || (sc >= NSC_30)) return SCPE_ARG;
ad = (tr * NSC_30) + sc; /* decimal addr */
for (csum = 0; cnt; cnt--) { /* fill words */
if (load_getw (fi, &wd)) return SCPE_FMT;
Write (ad, wd);
csum = (csum + wd) & MMASK;
ad = (ad + 1) & AMASK;
}
if (!(sim_switches & SWMASK ('N'))) { /* unless -n, csum */
if (load_getw (fi, &wd)) return SCPE_FMT;
/* if ((csum ^wd) & MMASK) return SCPE_CSUM; */
}
break;
case 0x0: case 0x8: /* instructions */
if (load_geta (wd, &ad)) return SCPE_FMT; /* get address */
if ((wd & 0x00F00000) != 0x00900000) /* if not x, */
ad = (ad + amod) & AMASK; /* modify */
wd = (wd & (SIGN|I_OP)) + (ad << I_V_EA); /* instruction */
default: /* data word */
Write (origin, wd);
origin = (origin + 1) & AMASK;
break;
} /* end case */
} /* end for */
return SCPE_OK;
}
/* Symbol tables */
static const char opcode[] = "ZBYRIDNMPEUTHCAS";
@@ -199,9 +213,9 @@ static const char hex_decode[] = "0123456789FGJKQW";
void lgp_fprint_addr (FILE *st, DEVICE *dptr, t_addr addr)
{
if ((dptr == sim_devices[0]) &&
((sim_switches & SWMASK ('T')) ||
((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N')))))
fprintf (st, "%02d%02d", addr >> 6, addr & SCMASK_30);
((sim_switches & SWMASK ('T')) ||
((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N')))))
fprintf (st, "%02d%02d", addr >> 6, addr & SCMASK_30);
else fprint_val (st, addr, dptr->aradix, dptr->awidth, PV_LEFT);
return;
}
@@ -211,13 +225,15 @@ t_addr lgp_parse_addr (DEVICE *dptr, char *cptr, char **tptr)
t_addr ad, ea;
if ((dptr == sim_devices[0]) &&
((sim_switches & SWMASK ('T')) ||
((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N'))))) {
ad = (t_addr) strtotv (cptr, tptr, 10);
if (((ad / 100) >= NTK_30) || ((ad % 100) >= NSC_30)) {
*tptr = cptr;
return 0; }
ea = ((ad / 100) * NSC_30) | (ad % 100); }
((sim_switches & SWMASK ('T')) ||
((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N'))))) {
ad = (t_addr) strtotv (cptr, tptr, 10);
if (((ad / 100) >= NTK_30) || ((ad % 100) >= NSC_30)) {
*tptr = cptr;
return 0;
}
ea = ((ad / 100) * NSC_30) | (ad % 100);
}
else ea = (t_addr) strtotv (cptr, tptr, dptr->aradix);
return ea;
}
@@ -228,64 +244,69 @@ sim_vm_fprint_addr = &lgp_fprint_addr;
sim_vm_parse_addr = &lgp_parse_addr;
return;
}
/* Symbolic decode
Inputs:
*of = output stream
addr = current PC
*val = pointer to data
*uptr = pointer to unit
sw = switches
*of = output stream
addr = current PC
*val = pointer to data
*uptr = pointer to unit
sw = switches
Outputs:
return = status code
return = status code
*/
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
UNIT *uptr, int32 sw)
{
int32 i, c;
uint32 inst, op, ea;
inst = val[0];
if (sw & SWMASK ('A')) { /* alphabetic? */
if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG;
if (uptr->flags & UNIT_FLEX) { /* Flex file? */
c = flex_to_ascii[inst]; /* get ASCII equiv */
if (c <= 0) return SCPE_ARG; }
else c = inst & 0x7F; /* ASCII file */
fputc (c, of);
return SCPE_OK; }
if (sw & SWMASK ('A')) { /* alphabetic? */
if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG;
if (uptr->flags & UNIT_FLEX) { /* Flex file? */
c = flex_to_ascii[inst]; /* get ASCII equiv */
if (c <= 0) return SCPE_ARG;
}
else c = inst & 0x7F; /* ASCII file */
fputc (c, of);
return SCPE_OK;
}
if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */
if ((sw & SWMASK ('M')) && /* symbolic decode? */
if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */
if ((sw & SWMASK ('M')) && /* symbolic decode? */
((inst & ~(SIGN|I_OP|I_EA)) == 0)) {
op = I_GETOP (inst);
ea = I_GETEA (inst);
if (inst & SIGN) fputc ('-', of);
fprintf (of, "%c ", opcode[op]);
lgp_fprint_addr (of, sim_devices[0], ea);
return SCPE_OK; }
ea = I_GETEA (inst);
if (inst & SIGN) fputc ('-', of);
fprintf (of, "%c ", opcode[op]);
lgp_fprint_addr (of, sim_devices[0], ea);
return SCPE_OK;
}
if ((sw & SWMASK ('L')) || /* LGP hex? */
if ((sw & SWMASK ('L')) || /* LGP hex? */
((cpu_unit.flags & UNIT_LGPH_D) && !(sw & SWMASK ('H')))) {
for (i = 0; i < 8; i++) {
c = (inst >> (4 * (7 - i))) & 0xF;
fputc (hex_decode[c], of); }
return SCPE_OK; }
for (i = 0; i < 8; i++) {
c = (inst >> (4 * (7 - i))) & 0xF;
fputc (hex_decode[c], of);
}
return SCPE_OK;
}
return SCPE_ARG;
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
*uptr = pointer to unit
*val = pointer to output values
sw = switches
*cptr = pointer to input string
addr = current PC
*uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = error status
status = error status
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
@@ -293,30 +314,34 @@ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
int32 i, c;
char *tptr;
while (isspace (*cptr)) cptr++; /* absorb spaces */
while (isspace (*cptr)) cptr++; /* absorb spaces */
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) {
if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG;
if (uptr->flags & UNIT_FLEX) { /* Flex file? */
c = ascii_to_flex[*cptr & 0x7F]; /* get Flex equiv */
if (c < 0) return SCPE_ARG;
val[0] = ((c >> 1) | (c << 5)) & 0x3F; } /* transpose */
else val[0] = *cptr & 0x7F; /* ASCII file */
return SCPE_OK; }
if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG;
if (uptr->flags & UNIT_FLEX) { /* Flex file? */
c = ascii_to_flex[*cptr & 0x7F]; /* get Flex equiv */
if (c < 0) return SCPE_ARG;
val[0] = ((c >> 1) | (c << 5)) & 0x3F; /* transpose */
}
else val[0] = *cptr & 0x7F; /* ASCII file */
return SCPE_OK;
}
if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */
if (!parse_sym_m (cptr, val, sw)) return SCPE_OK; /* symbolic parse? */
if ((sw & SWMASK ('L')) || /* LGP hex? */
if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */
if (!parse_sym_m (cptr, val, sw)) return SCPE_OK; /* symbolic parse? */
if ((sw & SWMASK ('L')) || /* LGP hex? */
((cpu_unit.flags & UNIT_LGPH_D) && !(sw & SWMASK ('H')))) {
val[0] = 0;
while (isspace (*cptr)) cptr++; /* absorb spaces */
for (i = 0; i < 8; i++) {
c = *cptr++; /* get char */
if (c == 0) return SCPE_OK;
if (islower (c)) c = toupper (c);
if (tptr = strchr (hex_decode, c))
val[0] = (val[0] << 4) | (tptr - hex_decode);
else return SCPE_ARG; }
if (*cptr == 0) return SCPE_OK; }
val[0] = 0;
while (isspace (*cptr)) cptr++; /* absorb spaces */
for (i = 0; i < 8; i++) {
c = *cptr++; /* get char */
if (c == 0) return SCPE_OK;
if (islower (c)) c = toupper (c);
if (tptr = strchr (hex_decode, c))
val[0] = (val[0] << 4) | (tptr - hex_decode);
else return SCPE_ARG;
}
if (*cptr == 0) return SCPE_OK;
}
return SCPE_ARG;
}
@@ -328,19 +353,20 @@ uint32 ea, sgn;
char *tptr, gbuf[CBUFSIZE];
if (*cptr == '-') {
cptr++;
sgn = SIGN; }
cptr++;
sgn = SIGN;
}
else sgn = 0;
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
if (gbuf[1] != 0) return SCPE_ARG;
if (tptr = strchr (opcode, gbuf[0]))
val[0] = ((tptr - opcode) << I_V_OP) | sgn; /* merge opcode */
val[0] = ((tptr - opcode) << I_V_OP) | sgn; /* merge opcode */
else return SCPE_ARG;
cptr = get_glyph (cptr, gbuf, 0); /* get address */
cptr = get_glyph (cptr, gbuf, 0); /* get address */
ea = lgp_parse_addr (sim_devices[0], gbuf, &tptr);
if ((tptr == gbuf) || (*tptr != 0) || (ea > AMASK))
return SCPE_ARG;
val[0] = val[0] | (ea << I_V_EA); /* merge address */
return SCPE_ARG;
val[0] = val[0] | (ea << I_V_EA); /* merge address */
if (*cptr != 0) return SCPE_2MARG;
return SCPE_OK;
}