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:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
753
LGP/lgp_cpu.c
753
LGP/lgp_cpu.c
@@ -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;
|
||||
}
|
||||
|
||||
147
LGP/lgp_defs.h
147
LGP/lgp_defs.h
@@ -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 */
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
694
LGP/lgp_stddev.c
694
LGP/lgp_stddev.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
352
LGP/lgp_sys.c
352
LGP/lgp_sys.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user