~ubuntu-branches/ubuntu/jaunty/simh/jaunty

« back to all changes in this revision

Viewing changes to HP2100/hp2100_cpu.c

  • Committer: Bazaar Package Importer
  • Author(s): Vince Mulhollon
  • Date: 2007-04-13 20:16:15 UTC
  • mfrom: (1.1.7 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20070413201615-jiar46bgkrs0dw2h
Tags: 3.7.0-1
* New upstream released 03-Feb-2007
* i7094 added which emulates the IBM 7090/7094
* Upstream has converted almost entirely to pdf format for docs
* All manpages updated
* All docs are registered with the doc-base system

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* hp2100_cpu.c: HP 2100 CPU simulator
 
1
/* hp2100_cpu.c: HP 21xx CPU simulator
2
2
 
3
 
   Copyright (c) 1993-2005, Robert M. Supnik
 
3
   Copyright (c) 1993-2007, Robert M. Supnik
4
4
 
5
5
   Permission is hereby granted, free of charge, to any person obtaining a
6
6
   copy of this software and associated documentation files (the "Software"),
23
23
   used in advertising or otherwise to promote the sale, use or other dealings
24
24
   in this Software without prior written authorization from Robert M Supnik.
25
25
 
26
 
   CPU          2116A/2100A/21MX-M/21MX-E central processing unit
27
 
   MP           12892B memory protect
28
 
   DMA0,DMA1    12895A/12897B direct memory access/dual channel port controller
 
26
   CPU          2114C/2115A/2116C/2100A/1000-M/E/F central processing unit
 
27
   MP           12581A/12892B memory protect
 
28
   DMA0,DMA1    12607B/12578A/12895A direct memory access controller
 
29
   DCPC0,DCPC1  12897B dual channel port controller
29
30
 
 
31
   11-Jan-07    JDB     Added 12578A DMA byte packing
 
32
   28-Dec-06    JDB     CLC 0 now sends CRS instead of CLC to devices
 
33
   26-Dec-06    JDB     Fixed improper IRQ deferral for 21xx CPUs
 
34
                        Fixed improper interrupt servicing in resolve
 
35
   21-Dec-06    JDB     Added 21xx loader enable/disable support
 
36
   16-Dec-06    JDB     Added 2114 and 2115 CPU options.
 
37
                        Added support for 12607B (2114) and 12578A (2115/6) DMA
 
38
   01-Dec-06    JDB     Added 1000-F CPU option (requires HAVE_INT64)
 
39
                        SHOW CPU displays 1000-M/E instead of 21MX-M/E
 
40
   16-Oct-06    JDB     Moved ReadF to hp2100_cpu1.c
 
41
   12-Oct-06    JDB     Fixed INDMAX off-by-one error in resolve
 
42
   26-Sep-06    JDB     Added iotrap parameter to UIG dispatchers for RTE microcode
 
43
   12-Sep-06    JDB     iogrp returns NOTE_IOG to recalc interrupts
 
44
                        resolve returns NOTE_INDINT to service held-off interrupt
 
45
   16-Aug-06    JDB     Added support for future microcode options, future F-Series
 
46
   09-Aug-06    JDB     Added double integer microcode, 1000-M/E synonyms
 
47
                        Enhanced CPU option validity checking
 
48
                        Added DCPC as a synonym for DMA for 21MX simulations
30
49
   26-Dec-05    JDB     Improved reporting in dev_conflict
31
50
   22-Sep-05    RMS     Fixed declarations (from Sterling Garwood)
32
51
   21-Jan-05    JDB     Reorganized CPU option flags
98
117
   15-Oct-00    RMS     Added dynamic device number support
99
118
 
100
119
   References:
101
 
   - 21MX M-Series Computer, HP 2108B and HP 2112B, Operating and Reference Manual
102
 
       (02108-90037, Apr-1979)
 
120
   - 2100A Computer Reference Manual (02100-90001, Dec-1971)
 
121
   - HP 1000 M/E/F-Series Computers Technical Reference Handbook
 
122
        (5955-0282, Mar-1980)
103
123
   - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
104
124
       (92851-90001, Mar-1981)
 
125
   - 12607A Direct Memory Access Operating and Service Manual
 
126
       (12607-90002, Jan-1970)
 
127
   - 12578A/12578A-01 Direct Memory Access Operating and Service Manual
 
128
       (12578-9001, Mar-1972)
105
129
 
106
130
   The register state for the HP 2116 CPU is:
107
131
 
125
149
   YR<15:0>             Y register
126
150
   dms_sr<15:0>         dynamic memory system status register
127
151
   dms_vr<15:0>         dynamic memory system violation register
128
 
      
 
152
 
129
153
   The original HP 2116 has four instruction formats: memory reference,
130
154
   shift, alter/skip, and I/O.  The HP 2100 added extended memory reference
131
155
   and extended arithmetic.  The HP21MX added extended byte, bit, and word
293
317
        device controls as bit array dev_ctl[2][31..0]
294
318
        device service requests as bit array dev_srq[3][31..0]
295
319
 
296
 
      The HP 2100 interrupt structure is based on flag, flag buffer,.
 
320
      The HP 2100 interrupt structure is based on flag, flag buffer,
297
321
      and control.  If a device flag is set, the flag buffer is set,
298
322
      the control bit is set, and the device is the highest priority
299
323
      on the interrupt chain, it requests an interrupt.  When the
307
331
      devices don't need to track command separately from control.
308
332
 
309
333
      Service requests are used to trigger the DMA service logic.
310
 
 
 
334
 
311
335
   3. Non-existent memory.  On the HP 2100, reads to non-existent memory
312
336
      return zero, and writes are ignored.  In the simulator, the
313
337
      largest possible memory is instantiated and initialized to zero.
314
 
      Thus, only writes need be checked against actual memory size.
 
338
      Thus, only writes need be checked against memory size.
 
339
 
 
340
      On the 21xx machines, doing SET CPU LOADERDISABLE decreases available
 
341
      memory size by 64 words.
315
342
 
316
343
   4. Adding I/O devices.  These modules must be modified:
317
344
 
327
354
      instruction, the interrupt is taken at the appropriate point; but there
328
355
      is no testing for new interrupts during execution (that is, the event
329
356
      timer is not called).
 
357
 
 
358
   6. Interrupt deferral.  At instruction fetch time, a pending interrupt
 
359
      request may be deferred if the previous instruction was a JMP indirect,
 
360
      JSB indirect, STC, CLC, STF, CLF, SFS (1000 only), or SFC (1000 only), or
 
361
      was executing from an interrupt trap cell.  If the CPU is a 1000, then the
 
362
      request is always deferred until after the current instruction completes.
 
363
      If the CPU is a 21xx, then the request is deferred unless the current
 
364
      instruction is an MRG instruction other than JMP or JMP,I or JSB,I.  Note
 
365
      that for the 21xx, SFS and SFC are not included in the deferral criteria.
330
366
*/
331
367
 
332
368
#include "hp2100_defs.h"
333
369
#include <setjmp.h>
334
370
#include "hp2100_cpu.h"
335
371
 
 
372
/* Memory protect constants */
 
373
 
336
374
#define UNIT_V_MP_JSB   (UNIT_V_UF + 0)                 /* MP jumper W5 out */
337
375
#define UNIT_V_MP_INT   (UNIT_V_UF + 1)                 /* MP jumper W6 out */
338
376
#define UNIT_V_MP_SEL1  (UNIT_V_UF + 2)                 /* MP jumper W7 out */
340
378
#define UNIT_MP_INT     (1 << UNIT_V_MP_INT)
341
379
#define UNIT_MP_SEL1    (1 << UNIT_V_MP_SEL1)
342
380
 
343
 
#define MOD_211X        (1 << TYPE_211X)
344
 
#define MOD_2100        (1 << TYPE_2100)
345
 
#define MOD_21MX        (1 << TYPE_21MX)
346
 
#define MOD_CURRENT     (1 << CPU_TYPE)
347
 
 
348
 
#define UNIT_SYSTEM     (UNIT_CPU_MASK | UNIT_OPTS)
349
 
#define UNIT_SYS_2116   (UNIT_2116)
350
 
#define UNIT_SYS_2100   (UNIT_2100 | UNIT_EAU)
351
 
#define UNIT_SYS_21MX_M (UNIT_21MX_M | UNIT_EAU | UNIT_FP | UNIT_DMS)
352
 
#define UNIT_SYS_21MX_E (UNIT_21MX_E | UNIT_EAU | UNIT_FP | UNIT_DMS)
353
381
 
354
382
#define ABORT(val)      longjmp (save_env, (val))
355
383
 
365
393
uint32 PC = 0;                                          /* P register */
366
394
uint32 SR = 0;                                          /* S register */
367
395
uint32 MR = 0;                                          /* M register */
 
396
uint32 saved_MR = 0;                                    /* between executions */
368
397
uint32 TR = 0;                                          /* T register */
369
398
uint32 XR = 0;                                          /* X register */
370
399
uint32 YR = 0;                                          /* Y register */
393
422
uint32 ind_max = 16;                                    /* iadr nest limit */
394
423
uint32 stop_inst = 1;                                   /* stop on ill inst */
395
424
uint32 stop_dev = 0;                                    /* stop on ill dev */
 
425
uint32 fwanxm = 0;                                      /* first word addr of nx mem */
396
426
uint16 pcq[PCQ_SIZE] = { 0 };                           /* PC queue */
397
427
uint32 pcq_p = 0;                                       /* PC queue ptr */
398
428
REG *pcq_r = NULL;                                      /* PC queue reg ptr */
399
429
jmp_buf save_env;                                       /* abort handler */
400
430
 
401
 
struct opt_table {                                      /* options table */
402
 
    int32       optf;
403
 
    int32       cpuf;
404
 
    };
405
 
 
406
 
static struct opt_table opt_val[] = {
407
 
    { UNIT_EAU,  MOD_211X },
408
 
    { UNIT_FP,   MOD_2100 },
409
 
    { UNIT_DMS,  MOD_21MX },
410
 
    { UNIT_IOP,  MOD_2100 | MOD_21MX },
411
 
    { UNIT_FFP,  MOD_2100 | MOD_21MX },
412
 
    { TYPE_211X, MOD_211X | MOD_2100 | MOD_21MX },
413
 
    { TYPE_2100, MOD_211X | MOD_2100 | MOD_21MX },
414
 
    { TYPE_21MX, MOD_211X | MOD_2100 | MOD_21MX },
415
 
    { 0, 0 }
416
 
    };
 
431
/* Table of CPU features by model.
 
432
 
 
433
   Fields:
 
434
    - typ:    standard features plus typically configured options.
 
435
    - opt:    complete list of optional features.
 
436
    - maxmem: maximum configurable memory in 16-bit words.
 
437
 
 
438
   Features in the "typical" list are enabled when the CPU model is selected.
 
439
   If a feature appears in the "typical" list but NOT in the "optional" list,
 
440
   then it is standard equipment and cannot be disabled.  If a feature appears
 
441
   in the "optional" list, then it may be enabled or disabled as desired by the
 
442
   user.
 
443
*/
 
444
 
 
445
struct FEATURE_TABLE {                                  /* CPU model feature table: */
 
446
    uint32      typ;                                    /*  - typical features */
 
447
    uint32      opt;                                    /*  - optional features */
 
448
    uint32      maxmem;                                 /*  - maximum memory */
 
449
    };
 
450
 
 
451
static struct FEATURE_TABLE cpu_features[] = {          /* features in UNIT_xxxx order*/
 
452
  { UNIT_DMA | UNIT_MP,                                 /* UNIT_2116 */
 
453
    UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_EAU,
 
454
    32768 },
 
455
  { UNIT_DMA,                                           /* UNIT_2115 */
 
456
    UNIT_PFAIL | UNIT_DMA | UNIT_EAU,
 
457
    8192 },
 
458
  { UNIT_DMA,                                           /* UNIT_2114 */
 
459
    UNIT_PFAIL | UNIT_DMA,
 
460
    16384 },
 
461
  { 0, 0, 0 },
 
462
  { UNIT_PFAIL | UNIT_MP | UNIT_DMA | UNIT_EAU,         /* UNIT_2100 */
 
463
    UNIT_DMA   | UNIT_FP | UNIT_IOP | UNIT_FFP,
 
464
    32768 },
 
465
  { 0, 0, 0 },
 
466
  { 0, 0, 0 },
 
467
  { 0, 0, 0 },
 
468
  { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_M */
 
469
    UNIT_PFAIL | UNIT_DMA | UNIT_MP  | UNIT_DMS |
 
470
    UNIT_IOP   | UNIT_FFP | UNIT_DBI | UNIT_DS,
 
471
    1048576 },
 
472
  { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_E */
 
473
    UNIT_PFAIL | UNIT_DMA | UNIT_MP  | UNIT_DMS |
 
474
    UNIT_IOP   | UNIT_FFP | UNIT_DBI | UNIT_DS  | UNIT_EMA_VMA,
 
475
    1048576 },
 
476
  { UNIT_MP  | UNIT_DMA | UNIT_EAU | UNIT_FP |          /* UNIT_1000_F */
 
477
    UNIT_FFP | UNIT_DBI | UNIT_DMS,
 
478
    UNIT_PFAIL | UNIT_DMA | UNIT_MP     |
 
479
    UNIT_IOP   | UNIT_DS  | UNIT_SIGNAL | UNIT_EMA_VMA,
 
480
    1048576 }
 
481
  };
417
482
 
418
483
extern int32 sim_interval;
419
484
extern int32 sim_int_char;
444
509
t_stat mp_reset (DEVICE *dptr);
445
510
t_stat dma0_reset (DEVICE *dptr);
446
511
t_stat dma1_reset (DEVICE *dptr);
447
 
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
448
 
t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc);
 
512
t_stat cpu_set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc);
 
513
t_stat cpu_set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc);
 
514
t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc);
 
515
t_stat cpu_set_opt (UNIT *uptr, int32 option, char *cptr, void *desc);
 
516
t_stat cpu_clr_opt (UNIT *uptr, int32 option, char *cptr, void *desc);
 
517
t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc);
449
518
t_bool dev_conflict (void);
450
519
void hp_post_cmd (t_bool from_scp);
451
520
 
452
521
extern t_stat cpu_eau (uint32 IR, uint32 intrq);
453
 
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq);
454
 
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq);
 
522
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap);
 
523
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap);
 
524
 
455
525
extern int32 clk_delay (int32 flg);
456
526
extern void (*sim_vm_post) (t_bool from_scp);
457
527
 
463
533
   cpu_mod      CPU modifiers list
464
534
*/
465
535
 
466
 
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, VASIZE) };
 
536
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, 0) };
467
537
 
468
538
REG cpu_reg[] = {
469
539
    { ORDATA (P, PC, 15) },
488
558
    { FLDATA (STOP_INST, stop_inst, 0) },
489
559
    { FLDATA (STOP_DEV, stop_dev, 1) },
490
560
    { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
 
561
    { ORDATA (FWANXM, fwanxm, 32), REG_HRO },
491
562
    { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC },
492
563
    { ORDATA (PCQP, pcq_p, 6), REG_HRO },
493
564
    { ORDATA (WRU, sim_int_char, 8), REG_HRO },
506
577
    { NULL }
507
578
    };
508
579
 
 
580
/* CPU modifier table.
 
581
 
 
582
   The 21MX monikers are deprecated in favor of the 1000 designations.  See the
 
583
   "HP 1000 Series Naming History" on the back inside cover of the Technical
 
584
   Reference Handbook. */
 
585
 
509
586
MTAB cpu_mod[] = {
510
 
    { UNIT_SYSTEM, UNIT_SYS_2116,   NULL, "2116",   &cpu_set_opt, NULL,
511
 
      (void *) TYPE_211X },
512
 
    { UNIT_SYSTEM, UNIT_SYS_2100,   NULL, "2100",   &cpu_set_opt, NULL,
513
 
      (void *) TYPE_2100 },
514
 
    { UNIT_SYSTEM, UNIT_SYS_21MX_E, NULL, "21MX-E", &cpu_set_opt, NULL,
515
 
      (void *) TYPE_21MX },
516
 
    { UNIT_SYSTEM, UNIT_SYS_21MX_M, NULL, "21MX-M", &cpu_set_opt, NULL,
517
 
      (void *) TYPE_21MX },
518
 
 
519
 
    { UNIT_CPU_MASK, UNIT_2116,   "2116",   NULL, NULL },
520
 
    { UNIT_CPU_MASK, UNIT_2100,   "2100",   NULL, NULL },
521
 
    { UNIT_CPU_MASK, UNIT_21MX_E, "21MX-E", NULL, NULL },
522
 
    { UNIT_CPU_MASK, UNIT_21MX_M, "21MX-M", NULL, NULL },
523
 
 
524
 
    { UNIT_EAU, UNIT_EAU, "EAU",    "EAU",   &cpu_set_opt, NULL,
525
 
      (void *) UNIT_EAU },
526
 
    { UNIT_EAU, 0,        "no EAU", "NOEAU", &cpu_set_opt, NULL,
527
 
      (void *) UNIT_EAU },
528
 
    { UNIT_FP,  UNIT_FP,  "FP",     "FP",    &cpu_set_opt, NULL,
529
 
      (void *) UNIT_FP },
530
 
    { UNIT_FP,  0,        "no FP",  "NOFP",  &cpu_set_opt, NULL,
531
 
      (void *) UNIT_FP },
532
 
    { UNIT_IOP, UNIT_IOP, "IOP",    "IOP",   &cpu_set_opt, NULL,
533
 
      (void *) UNIT_IOP },
534
 
    { UNIT_IOP, 0,        "no IOP", "NOIOP", &cpu_set_opt, NULL,
535
 
      (void *) UNIT_IOP },
536
 
    { UNIT_DMS, UNIT_DMS, "DMS",    "DMS",   &cpu_set_opt, NULL,
537
 
      (void *) UNIT_DMS },
538
 
    { UNIT_DMS, 0,        "no DMS", "NODMS", &cpu_set_opt, NULL,
539
 
      (void *) UNIT_DMS },
540
 
    { UNIT_FFP, UNIT_FFP, "FFP",    "FFP",   &cpu_set_opt, NULL,
541
 
      (void *) UNIT_FFP },
542
 
    { UNIT_FFP, 0,        "no FFP", "NOFFP", &cpu_set_opt, NULL,
543
 
      (void *) UNIT_FFP },
544
 
    { MTAB_XTD | MTAB_VDV,    4096, NULL, "4K",    &cpu_set_size },
545
 
    { MTAB_XTD | MTAB_VDV,    8192, NULL, "8K",    &cpu_set_size },
546
 
    { MTAB_XTD | MTAB_VDV,   16384, NULL, "16K",   &cpu_set_size },
547
 
    { MTAB_XTD | MTAB_VDV,   32768, NULL, "32K",   &cpu_set_size },
548
 
    { MTAB_XTD | MTAB_VDV,   65536, NULL, "64K",   &cpu_set_size },
549
 
    { MTAB_XTD | MTAB_VDV,  131072, NULL, "128K",  &cpu_set_size },
550
 
    { MTAB_XTD | MTAB_VDV,  262144, NULL, "256K",  &cpu_set_size },
551
 
    { MTAB_XTD | MTAB_VDV,  524288, NULL, "512K",  &cpu_set_size },
552
 
    { MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size },
 
587
    { UNIT_MODEL_MASK, UNIT_2116,   "",   "2116",   &cpu_set_model, &cpu_show_model, "2116"   },
 
588
    { UNIT_MODEL_MASK, UNIT_2115,   "",   "2115",   &cpu_set_model, &cpu_show_model, "2115"   },
 
589
    { UNIT_MODEL_MASK, UNIT_2114,   "",   "2114",   &cpu_set_model, &cpu_show_model, "2114"   },
 
590
    { UNIT_MODEL_MASK, UNIT_2100,   "",   "2100",   &cpu_set_model, &cpu_show_model, "2100"   },
 
591
    { UNIT_MODEL_MASK, UNIT_1000_E, "",   "1000-E", &cpu_set_model, &cpu_show_model, "1000-E" },
 
592
    { UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &cpu_set_model, &cpu_show_model, "1000-E" },
 
593
    { UNIT_MODEL_MASK, UNIT_1000_M, "",   "1000-M", &cpu_set_model, &cpu_show_model, "1000-M" },
 
594
    { UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &cpu_set_model, &cpu_show_model, "1000-M" },
 
595
 
 
596
#if defined (HAVE_INT64)
 
597
    { UNIT_MODEL_MASK, UNIT_1000_F, "",   "1000-F", &cpu_set_model, &cpu_show_model, "1000-F" },
 
598
#endif
 
599
 
 
600
    { MTAB_XTD | MTAB_VDV, 1, NULL, "LOADERENABLE",  &cpu_set_ldr, NULL, NULL },
 
601
    { MTAB_XTD | MTAB_VDV, 0, NULL, "LOADERDISABLE", &cpu_set_ldr, NULL, NULL },
 
602
 
 
603
    { UNIT_EAU,     UNIT_EAU,   "EAU",        "EAU",      &cpu_set_opt, NULL, NULL },
 
604
    { UNIT_EAU,     0,          "no EAU",     NULL,       NULL,         NULL, NULL },
 
605
    { MTAB_XTD | MTAB_VDV, UNIT_EAU,    NULL, "NOEAU",    &cpu_clr_opt, NULL, NULL },
 
606
 
 
607
    { UNIT_FP,      UNIT_FP,    "FP",         "FP",       &cpu_set_opt, NULL, NULL },
 
608
    { UNIT_FP,      0,          "no FP",      NULL,       NULL,         NULL, NULL },
 
609
    { MTAB_XTD | MTAB_VDV, UNIT_FP,     NULL, "NOFP",     &cpu_clr_opt, NULL, NULL },
 
610
 
 
611
    { UNIT_IOP,     UNIT_IOP,   "IOP",        "IOP",      &cpu_set_opt, NULL, NULL },
 
612
    { UNIT_IOP,     0,          "no IOP",     NULL,       NULL,         NULL, NULL },
 
613
    { MTAB_XTD | MTAB_VDV, UNIT_IOP,    NULL, "NOIOP",    &cpu_clr_opt, NULL, NULL },
 
614
 
 
615
    { UNIT_DMS,     UNIT_DMS,   "DMS",        "DMS",      &cpu_set_opt, NULL, NULL },
 
616
    { UNIT_DMS,     0,          "no DMS",     NULL,       NULL,         NULL, NULL },
 
617
    { MTAB_XTD | MTAB_VDV, UNIT_DMS,    NULL, "NODMS",    &cpu_clr_opt, NULL, NULL },
 
618
 
 
619
    { UNIT_FFP,     UNIT_FFP,   "FFP",        "FFP",      &cpu_set_opt, NULL, NULL },
 
620
    { UNIT_FFP,     0,          "no FFP",     NULL,       NULL,         NULL, NULL },
 
621
    { MTAB_XTD | MTAB_VDV, UNIT_FFP,    NULL, "NOFFP",    &cpu_clr_opt, NULL, NULL },
 
622
 
 
623
    { UNIT_DBI,     UNIT_DBI,   "DBI",        "DBI",      &cpu_set_opt, NULL, NULL },
 
624
    { UNIT_DBI,     0,          "no DBI",     NULL,       NULL,         NULL, NULL },
 
625
    { MTAB_XTD | MTAB_VDV, UNIT_DBI,    NULL, "NODBI",    &cpu_clr_opt, NULL, NULL },
 
626
 
 
627
/* Future microcode support.
 
628
    { UNIT_EMA_VMA, UNIT_EMA,   "EMA",        "EMA",      &cpu_set_opt, NULL, NULL },
 
629
    { MTAB_XTD | MTAB_VDV, UNIT_EMA,    NULL, "NOEMA",    &cpu_clr_opt, NULL, NULL },
 
630
 
 
631
    { UNIT_EMA_VMA, UNIT_VMAOS, "VMA",        "VMA",      &cpu_set_opt, NULL, NULL },
 
632
    { MTAB_XTD | MTAB_VDV, UNIT_VMAOS,  NULL, "NOVMA",    &cpu_clr_opt, NULL, NULL },
 
633
 
 
634
    { UNIT_EMA_VMA, 0,          "no EMA/VMA", NULL,       &cpu_set_opt, NULL, NULL },
 
635
 
 
636
    { UNIT_VIS,     UNIT_VIS,   "VIS",        "VIS",      &cpu_set_opt, NULL, NULL },
 
637
    { UNIT_VIS,     0,          "no VIS",     NULL,       NULL,         NULL, NULL },
 
638
    { MTAB_XTD | MTAB_VDV, UNIT_VIS,    NULL, "NOVIS",    &cpu_clr_opt, NULL, NULL },
 
639
 
 
640
    { UNIT_DS,      UNIT_DS,    "DS",         "DS",       &cpu_set_opt, NULL, NULL },
 
641
    { UNIT_DS,      0,          "no DS",      NULL,       NULL,         NULL, NULL },
 
642
    { MTAB_XTD | MTAB_VDV, UNIT_DS,     NULL, "NODS",     &cpu_clr_opt, NULL, NULL },
 
643
 
 
644
    { UNIT_SIGNAL,  UNIT_SIGNAL,"SIGNAL",     "SIGNAL",   &cpu_set_opt, NULL, NULL },
 
645
    { UNIT_SIGNAL,  0,          "no SIGNAL",  NULL,       NULL,         NULL, NULL },
 
646
    { MTAB_XTD | MTAB_VDV, UNIT_SIGNAL, NULL, "NOSIGNAL", &cpu_clr_opt, NULL, NULL },
 
647
*/
 
648
 
 
649
    { MTAB_XTD | MTAB_VDV,    4096, NULL, "4K",    &cpu_set_size, NULL, NULL },
 
650
    { MTAB_XTD | MTAB_VDV,    8192, NULL, "8K",    &cpu_set_size, NULL, NULL },
 
651
    { MTAB_XTD | MTAB_VDV,   12288, NULL, "12K",   &cpu_set_size, NULL, NULL },
 
652
    { MTAB_XTD | MTAB_VDV,   16384, NULL, "16K",   &cpu_set_size, NULL, NULL },
 
653
    { MTAB_XTD | MTAB_VDV,   24576, NULL, "24K",   &cpu_set_size, NULL, NULL },
 
654
    { MTAB_XTD | MTAB_VDV,   32768, NULL, "32K",   &cpu_set_size, NULL, NULL },
 
655
    { MTAB_XTD | MTAB_VDV,   65536, NULL, "64K",   &cpu_set_size, NULL, NULL },
 
656
    { MTAB_XTD | MTAB_VDV,  131072, NULL, "128K",  &cpu_set_size, NULL, NULL },
 
657
    { MTAB_XTD | MTAB_VDV,  262144, NULL, "256K",  &cpu_set_size, NULL, NULL },
 
658
    { MTAB_XTD | MTAB_VDV,  524288, NULL, "512K",  &cpu_set_size, NULL, NULL },
 
659
    { MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size, NULL, NULL },
553
660
    { 0 }
554
661
    };
555
662
 
616
723
    { ORDATA (CW1, dmac[0].cw1, 16) },
617
724
    { ORDATA (CW2, dmac[0].cw2, 16) },
618
725
    { ORDATA (CW3, dmac[0].cw3, 16) },
 
726
    { DRDATA (LATENCY, dmac[0].latency, 8) },
 
727
    { FLDATA (BYTE, dmac[0].packer, 31) },
 
728
    { ORDATA (PACKER, dmac[0].packer, 8) },
619
729
    { NULL }
620
730
    };
621
731
 
638
748
    { ORDATA (CW1, dmac[1].cw1, 16) },
639
749
    { ORDATA (CW2, dmac[1].cw2, 16) },
640
750
    { ORDATA (CW3, dmac[1].cw3, 16) },
 
751
    { DRDATA (LATENCY, dmac[1].latency, 8) },
 
752
    { FLDATA (BYTE, dmac[1].packer, 31) },
 
753
    { ORDATA (PACKER, dmac[1].packer, 8) },
641
754
    { NULL }
642
755
    };
643
756
 
649
762
    NULL, DEV_DISABLE
650
763
    };
651
764
 
652
 
/* Interrupt defer table */
 
765
/* Interrupt defer table (1000 version) */
653
766
 
654
 
static const int32 defer_tab[] = { 0, 1, 1, 1, 0, 0, 0, 1 };
 
767
static int32 defer_tab[] = { 0, 1, 1, 1, 0, 0, 0, 1 };
655
768
 
656
769
/* Device dispatch table */
657
770
 
730
843
    }
731
844
sim_rtc_init (clk_delay (0));                           /* recalibrate clock */
732
845
 
 
846
/* Configure interrupt deferral table */
 
847
 
 
848
if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX)                /* 21xx series? */
 
849
    defer_tab[ioSFC] = defer_tab[ioSFS] = 0;            /* SFC/S doesn't defer */
 
850
else                                                    /* 1000 series */
 
851
    defer_tab[ioSFC] = defer_tab[ioSFS] = 1;            /* SFC/S does defer */
 
852
 
733
853
/* Abort handling
734
854
 
735
855
   If an abort occurs in memory protection, the relocation routine
765
885
        intrq = calc_int ();                            /* recalc interrupts */
766
886
        }
767
887
 
 
888
/* Interrupt deferral rules differ on the 21xx vs. the 1000.  The 1000 always
 
889
   defers until the completion of the instruction following a deferring
 
890
   instruction.  The 21xx defers unless the current instruction is an MRG
 
891
   instruction other than JMP or JMP,I or JSB,I.  See the "Set Phase Logic
 
892
   Flowchart" in the 2100A Computer Reference Manual for details.
 
893
*/
 
894
 
 
895
    if (intrq &&                                        /* interrupt pending? */
 
896
       ion_defer &&                                     /* deferring instruction? */
 
897
       (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX)) {         /* 21xx series? */
 
898
        IR = ReadW (PC);                                /* prefetch next instr */
 
899
        if (((IR & 0070000) != 0000000) &&              /* MRG instruction? */
 
900
            ((IR & 0174000) != 0114000) &&              /* JSB,I? */
 
901
            ((IR & 0074000) != 0024000))                /* JMP or JMP,I? */
 
902
            ion_defer = 0;                              /* no, so clear deferral */
 
903
            }
 
904
 
768
905
/*  (From Dave Bryan)
769
906
    Unlike most other I/O devices, the MP flag flip-flop is cleared
770
907
    automatically when the interrupt is acknowledged and not by a programmed
774
911
    92851-90001) says:
775
912
 
776
913
      "When IAK occurs and IRQ5 is asserted, the FLAGBFF is cleared, FLAGFF
777
 
       clocked off at next T2, and IRQ5 will no longer occur." */
 
914
       clocked off at next T2, and IRQ5 will no longer occur."
 
915
*/
778
916
 
779
917
    if (intrq && ((intrq <= PRO) || !ion_defer)) {      /* interrupt request? */
780
918
        iotrap = 1;                                     /* I/O trap cell instr */
827
965
    1  0  0  0  1  0  0  1      double store (decoded as 104400)
828
966
    1  0  0  0  1  0  1  0      extended instr group 0 (A/B must be set)
829
967
    1  0  0  0  x  0  1  1      extended instr group 1 (A/B ignored) */
830
 
    
 
968
 
831
969
    absel = (IR & I_AB)? 1: 0;                          /* get A/B select */
832
970
    switch ((IR >> 8) & 0377) {                         /* decode IR<15:8> */
833
971
 
841
979
        AR = AR & ReadW (MA);
842
980
        break;
843
981
 
 
982
    case 0230:case 0231:case 0232:case 0233:
 
983
    case 0234:case 0235:case 0236:case 0237:
 
984
        ion_defer = 1;                                  /* defer if JSB,I */
 
985
 
844
986
    case 0030:case 0031:case 0032:case 0033:
845
987
    case 0034:case 0035:case 0036:case 0037:
846
 
    case 0230:case 0231:case 0232:case 0233:
847
 
    case 0234:case 0235:case 0236:case 0237:
848
988
        if (reason = Ea (IR, &MA, intrq)) break;        /* JSB */
849
989
        if ((mp_unit.flags & UNIT_MP_JSB) &&            /* MP if W7 (JSB) out */
850
990
            CTL (PRO) && (MA < mp_fence))
852
992
        WriteW (MA, PC);                                /* store PC */
853
993
        PCQ_ENTRY;
854
994
        PC = (MA + 1) & VAMASK;                         /* jump */
855
 
        if (IR & I_IA) ion_defer = 1;                   /* ind? defer intr */
856
995
        break;
857
996
 
858
997
    case 0040:case 0041:case 0042:case 0043:
863
1002
        AR = AR ^ ReadW (MA);
864
1003
        break;
865
1004
 
 
1005
    case 0250:case 0251:case 0252:case 0253:
 
1006
    case 0254:case 0255:case 0256:case 0257:
 
1007
        ion_defer = 1;                                  /* defer if JMP,I */
 
1008
 
866
1009
    case 0050:case 0051:case 0052:case 0053:
867
1010
    case 0054:case 0055:case 0056:case 0057:
868
 
    case 0250:case 0251:case 0252:case 0253:
869
 
    case 0254:case 0255:case 0256:case 0257:
870
1011
        if (reason = Ea (IR, &MA, intrq)) break;        /* JMP */
871
1012
        mp_dms_jmp (MA);                                /* validate jump addr */
872
1013
        PCQ_ENTRY;
873
1014
        PC = MA;                                        /* jump */
874
 
        if (IR & I_IA) ion_defer = 1;                   /* ind? defer int */
875
1015
        break;
876
1016
 
877
1017
    case 0060:case 0061:case 0062:case 0063:
1025
1165
    case 0204:case 0205:case 0206:case 0207:
1026
1166
    case 0214:case 0215:case 0216:case 0217:
1027
1167
        reason = iogrp (IR, iotrap);                    /* execute instr */
1028
 
        dmarq = calc_dma ();                            /* recalc DMA */
1029
 
        intrq = calc_int ();                            /* recalc interrupts */
1030
1168
        break;                                          /* end if I/O */
1031
1169
 
1032
1170
/* Extended arithmetic */
1042
1180
/* Extended instructions */
1043
1181
 
1044
1182
    case 0212:                                          /* UIG 0 extension */
1045
 
        reason = cpu_uig_0 (IR, intrq);                 /* extended opcode */
1046
 
        dmarq = calc_dma ();                            /* recalc DMA masks */
1047
 
        intrq = calc_int ();                            /* recalc interrupts */
 
1183
        reason = cpu_uig_0 (IR, intrq, iotrap);         /* extended opcode */
1048
1184
        break;
1049
1185
 
1050
1186
    case 0203:                                          /* UIG 1 extension */
1051
1187
    case 0213:
1052
 
        reason = cpu_uig_1 (IR, intrq);                 /* extended opcode */
1053
 
        dmarq = calc_dma ();                            /* recalc DMA masks */
1054
 
        intrq = calc_int ();                            /* recalc interrupts */
 
1188
        reason = cpu_uig_1 (IR, intrq, iotrap);         /* extended opcode */
1055
1189
        break;
1056
1190
        }                                               /* end case IR */
1057
1191
 
1058
 
    if (reason == STOP_INDINT) {                        /* indirect intr? */
 
1192
    if (reason == NOTE_IOG) {                           /* I/O instr exec? */
 
1193
        dmarq = calc_dma ();                            /* recalc DMA masks */
 
1194
        intrq = calc_int ();                            /* recalc interrupts */
 
1195
        reason = 0;                                     /* continue */
 
1196
        }
 
1197
 
 
1198
    else if (reason == NOTE_INDINT) {                   /* intr pend during indir? */
1059
1199
        PC = err_PC;                                    /* back out of inst */
1060
 
        ion_defer = 0;                                  /* clear defer */
1061
1200
        reason = 0;                                     /* continue */
1062
1201
        }
1063
1202
    }                                                   /* end while */
1069
1208
if (iotrap && (reason == STOP_HALT)) MR = intaddr;      /* HLT in trap cell? */
1070
1209
else MR = (PC - 1) & VAMASK;                            /* no, M = P - 1 */
1071
1210
TR = ReadTAB (MR);                                      /* last word fetched */
 
1211
saved_MR = MR;                                          /* save for T cmd update */
1072
1212
if ((reason == STOP_RSRV) || (reason == STOP_IODV) ||   /* instr error? */
1073
1213
    (reason == STOP_IND)) PC = err_PC;                  /* back up PC */
1074
1214
dms_upd_sr ();                                          /* update dms_sr */
 
1215
if (reason == STOP_HALT)                                /* programmed halt? */
 
1216
    cpu_set_ldr (NULL, FALSE, NULL, NULL);              /* disable loader (ignore errors) */
1075
1217
for (i = 0; dptr = sim_devices[i]; i++) {               /* loop thru dev */
1076
1218
    dibp = (DIB *) dptr->ctxt;                          /* get DIB */
1077
1219
    if (dibp) {                                         /* exist? */
1087
1229
return reason;
1088
1230
}
1089
1231
 
1090
 
/* Resolve indirect addresses */
 
1232
/* Resolve indirect addresses.
 
1233
 
 
1234
   An indirect chain is followed until a direct address is obtained.  Under
 
1235
   simulation, a maximum number of indirect levels are allowed (typically 16),
 
1236
   after which the instruction will be aborted.
 
1237
 
 
1238
   If the memory protect feature is present, an indirect counter is used that
 
1239
   allows a pending interrupt to be serviced if more than three levels of
 
1240
   indirection are encountered.  If MP jumper W6 ("INT") is out and MP is
 
1241
   enabled, then pending interrupts are serviced immediately.  When employing
 
1242
   the indirect counter, the hardware clears a pending interrupt deferral after
 
1243
   the third indirection and aborts the instruction after the fourth.
 
1244
*/
1091
1245
 
1092
1246
t_stat resolve (uint32 MA, uint32 *addr, uint32 irq)
1093
1247
{
1094
1248
uint32 i;
 
1249
t_bool pending = (irq && !(mp_unit.flags & DEV_DIS));
 
1250
t_bool int_enable = ((mp_unit.flags & UNIT_MP_INT) && CTL(PRO));
1095
1251
 
1096
1252
for (i = 0; (i < ind_max) && (MA & I_IA); i++) {        /* resolve multilevel */
1097
 
    if (irq &&                                          /* int req? */
1098
 
        ((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) &&  /* ind > 3 or W6 out? */
1099
 
        !(mp_unit.flags & DEV_DIS))                     /* MP installed? */
1100
 
        return STOP_INDINT;                             /* break out */
1101
 
    MA = ReadW (MA & VAMASK);
 
1253
    if (pending) {                                      /* interrupt pending and MP enabled? */
 
1254
        if ((i == 2) || int_enable)                     /* 3rd level indirect or INT out? */
 
1255
            ion_defer = 0;                              /* reenable interrrupts */
 
1256
        if ((i > 2) || int_enable)                      /* 4th or higher or INT out? */
 
1257
            return NOTE_INDINT;                         /* break out now */
 
1258
        }
 
1259
    MA = ReadW (MA & VAMASK);                           /* follow address chain */
1102
1260
    }
1103
 
if (i >= ind_max) return STOP_IND;                      /* indirect loop? */
 
1261
if (MA & I_IA) return STOP_IND;                         /* indirect loop? */
1104
1262
*addr = MA;
1105
1263
return SCPE_OK;
1106
1264
}
1164
1322
 
1165
1323
t_stat iogrp (uint32 ir, uint32 iotrap)
1166
1324
{
1167
 
uint32 dev, sop, iodata, ab;
 
1325
uint32 dev, sop, iodata, iostat, ab;
1168
1326
 
1169
1327
ab = (ir & I_AB)? 1: 0;                                 /* get A/B select */
1170
1328
dev = ir & I_DEVMASK;                                   /* get device */
1184
1342
    sprintf (&halt_msg[len - 6], "%06o", ir);           /* add the halt */
1185
1343
    return STOP_HALT;
1186
1344
    }
1187
 
return (iodata >> IOT_V_REASON);                        /* return status */
 
1345
iostat = iodata >> IOT_V_REASON;
 
1346
if (iostat == SCPE_OK) return NOTE_IOG;                 /* normal status */
 
1347
else return iostat;                                     /* abnormal status */
1188
1348
}
1189
1349
 
1190
1350
/* Device dispatch */
1304
1464
return ReadPW (pa);
1305
1465
}
1306
1466
 
1307
 
uint32 ReadF (uint32 va)
1308
 
{
1309
 
uint32 t = ReadW (va);
1310
 
uint32 t1 = ReadW ((va + 1) & VAMASK);
1311
 
return (t << 16) | t1;
1312
 
}
1313
 
 
1314
1467
uint16 ReadIO (uint32 va, uint32 map)
1315
1468
{
1316
1469
uint32 pa;
1340
1493
   writable, then whether the target is below the MP fence is not checked. [The
1341
1494
   simulator must] do MP check on all writes after DMS translation and violation
1342
1495
   checks are done (so, to pass, the page must be writable AND the target must
1343
 
   be above the MP fence). */
 
1496
   be above the MP fence).
 
1497
*/
1344
1498
 
1345
1499
#define MP_TEST(x)      (CTL (PRO) && ((x) > 1) && ((x) < mp_fence))
1346
1500
 
1519
1673
void dms_viol (uint32 va, uint32 st)
1520
1674
{
1521
1675
dms_vr = st | VA_GETPAG (va) |
1522
 
    ((st & (MVI_RPR | MVI_WPR))? MVI_MEB: 0) |          /* set MEB */   
 
1676
    ((st & (MVI_RPR | MVI_WPR))? MVI_MEB: 0) |          /* set MEB */
1523
1677
    (dms_enb? MVI_MEM: 0) |                             /* set MEM */
1524
1678
    (dms_ump? MVI_UMP: 0);                              /* set UMAP */
1525
1679
if (CTL (PRO)) {                                        /* protected? */
1544
1698
 
1545
1699
   NOTE: LIx/MIx reads floating I/O bus (0 on all machines).
1546
1700
 
 
1701
   NOTE: CLC 0 issues CRS to all devices, not CLC.  While most cards react
 
1702
   identically to CRS and CLC, some do not, e.g., the 12566B when used as an
 
1703
   I/O diagnostic target.  PRESET also issues CRS (with POPIO).
 
1704
 
1547
1705
   From Dave Bryan: RTE uses the undocumented instruction "SFS 0,C" to both test
1548
1706
   and turn off the interrupt system.  This is confirmed in the "RTE-6/VM
1549
1707
   Technical Specifications" manual (HP 92084-90015), section 2.3.1 "Process
1559
1717
    The major hole in being able to save the complete state is in saving the
1560
1718
    interrupt system state. In order to do this in both the 21MX and the 21XE
1561
1719
    the instruction 103300 was used to both test the interrupt system and
1562
 
    turn it off." */
 
1720
    turn it off."
 
1721
*/
1563
1722
 
1564
1723
int32 cpuio (int32 inst, int32 IR, int32 dat)
1565
1724
{
1584
1743
        break;
1585
1744
 
1586
1745
    case ioCTL:                                         /* control */
1587
 
        if (IR & I_CTL) {                               /* =CLC 02,03,06..77 */
1588
 
            devdisp (DMALT0, inst, I_CTL + DMALT0, 0);
1589
 
            devdisp (DMALT1, inst, I_CTL + DMALT1, 0);
1590
 
            for (i = 6; i <= I_DEVMASK; i++)
1591
 
                devdisp (i, inst, I_CTL + i, 0);
1592
 
            }
 
1746
        if (IR & I_CTL)                                 /* CLC 0 sends CRS */
 
1747
            for (i = 0; i <= I_DEVMASK; i++)            /* to all devices */
 
1748
                devdisp (i, ioCRS, I_CTL + i, 0);       /* IR -> "CLC i" for convenience */
1593
1749
        break;
1594
1750
 
1595
1751
    default:
1600
1756
return dat;
1601
1757
}
1602
1758
 
1603
 
/* Device 1 (overflow) I/O routine
 
1759
/* Device 1 (overflow/S-register) I/O routine
1604
1760
 
1605
 
   NOTE: The S register is read-only on the 2115/2116. */
 
1761
   NOTE: The S register is read-only on the 2115/2116.  It is read/write on
 
1762
   the 2114, 2100, and 1000.
 
1763
*/
1606
1764
 
1607
1765
int32 ovfio (int32 inst, int32 IR, int32 dat)
1608
1766
{
1629
1787
        break;
1630
1788
 
1631
1789
    case ioOTX:                                         /* output */
1632
 
        if (UNIT_CPU_TYPE != UNIT_TYPE_211X) SR = dat;
 
1790
        if ((UNIT_CPU_MODEL != UNIT_2116) &&
 
1791
            (UNIT_CPU_MODEL != UNIT_2115))
 
1792
            SR = dat;
1633
1793
        break;
1634
1794
 
1635
1795
    default:
1665
1825
 
1666
1826
   From Dave Bryan: Examination of the schematics for the MP card in the
1667
1827
   engineering documentation shows that the SFS and SFC I/O backplane signals
1668
 
   gate the output of the MEVFF onto the SKF line unconditionally. */
 
1828
   gate the output of the MEVFF onto the SKF line unconditionally.
 
1829
*/
1669
1830
 
1670
1831
int32 proio (int32 inst, int32 IR, int32 dat)
1671
1832
{
1692
1853
        if (cpu_unit.flags & UNIT_2100) iop_sp = mp_fence;
1693
1854
        break;
1694
1855
 
 
1856
    case ioCRS:                                         /* control reset */
1695
1857
    case ioCTL:                                         /* control clear/set */
1696
1858
        if ((IR & I_CTL) == 0) {                        /* STC */
1697
1859
            setCTL (PRO);
1709
1871
return dat;
1710
1872
}
1711
1873
 
1712
 
/* Devices 2,3 (secondary DMA) I/O routine */
 
1874
/* Devices 2,3 (secondary DMA) I/O routine.
 
1875
 
 
1876
   Implements control word 2 (memory address) and control word 3 (word count).
 
1877
 
 
1878
   The 12607B (2114) supports 14-bit addresses and 13-bit word counts.
 
1879
   The 12578A (2115/6) supports 15-bit addresses and 14-bit word counts.
 
1880
   The 12895A (2100) and 12897B (1000) support 15-bit addresses and 16-bit word
 
1881
   counts.
 
1882
 
 
1883
   Note: because the I/O bus floats to zero on 211x computers, LIA/MIA (word
 
1884
   count) returns zeros in the unused bit locations, even though the word count
 
1885
   is a negative value.
 
1886
*/
1713
1887
 
1714
1888
int32 dmsio (int32 inst, int32 IR, int32 dat)
1715
1889
{
1718
1892
ch = IR & 1;                                            /* get channel num */
1719
1893
switch (inst) {                                         /* case on opcode */
1720
1894
 
 
1895
    case ioLIX:                                         /* load remaining word count */
 
1896
        dat = 0;
 
1897
 
1721
1898
    case ioMIX:                                         /* merge */
1722
 
        dat = dat | dmac[ch].cw3;
1723
 
        break;
1724
 
 
1725
 
    case ioLIX:                                         /* load */
1726
 
        dat = dmac[ch].cw3;
 
1899
        if (UNIT_CPU_MODEL == UNIT_2114)                /* 2114? */
 
1900
            dat = dat | (dmac[ch].cw3 & 0017777);       /* only 13-bit count */
 
1901
        else if (UNIT_CPU_TYPE == UNIT_TYPE_211X)       /* 2115/2116? */
 
1902
            dat = dat | (dmac[ch].cw3 & 0037777);       /* only 14-bit count */
 
1903
        else
 
1904
            dat = dat | dmac[ch].cw3;                   /* rest use full value */
1727
1905
        break;
1728
1906
 
1729
1907
    case ioOTX:                                         /* output */
1730
 
        if (CTL (DMALT0 + ch)) dmac[ch].cw3 = dat;
1731
 
        else dmac[ch].cw2 = dat;
 
1908
        if (CTL (DMALT0 + ch))                          /* word count selected? */
 
1909
            dmac[ch].cw3 = dat;                         /* save count */
 
1910
        else                                            /* memory address selected */
 
1911
            if (UNIT_CPU_MODEL == UNIT_2114)            /* 2114? */
 
1912
                dmac[ch].cw2 = dat & 0137777;           /* 14-bit address */
 
1913
            else
 
1914
                dmac[ch].cw2 = dat;                     /* full address stored */
1732
1915
        break;
1733
1916
 
 
1917
    case ioCRS:                                         /* control reset */
1734
1918
    case ioCTL:                                         /* control clear/set */
1735
1919
        if (IR & I_CTL) { clrCTL (DMALT0 + ch); }       /* CLC */
1736
1920
        else { setCTL (DMALT0 + ch); }                  /* STC */
1745
1929
 
1746
1930
/* Devices 6,7 (primary DMA) I/O routine
1747
1931
 
1748
 
   NOTE: LIx/MIx reads floating S-bus (1 on 21MX, 0 on 2116/2100). */
 
1932
   Implements control word 1 (device address) and DMA control.
 
1933
 
 
1934
   The 12607B (2114) stores only bits 2-0 of the select code and interprets them
 
1935
   as select codes 10-16 (SRQ17 is not decoded).  The 12578A (2115/6), 12895A
 
1936
   (2100), and 12897B (1000) support the full 10-77 range of select codes.
 
1937
 
 
1938
   The 12578A supports byte-sized transfers by setting bit 14.  Bit 14 is
 
1939
   ignored by all other DMA cards, which support word transfers only.
 
1940
 
 
1941
   NOTE: LIx/MIx reads floating S-bus (1 on 21MX, 0 on 211x/2100).
 
1942
 
 
1943
   NOTE: CRS clears control and command flip-flops, whereas CLC clears only
 
1944
   control.
 
1945
*/
1749
1946
 
1750
1947
int32 dmpio (int32 inst, int32 IR, int32 dat)
1751
1948
{
1772
1969
 
1773
1970
    case ioLIX:                                         /* load */
1774
1971
        dat = 0;
 
1972
 
1775
1973
    case ioMIX:                                         /* merge */
1776
 
        if (UNIT_CPU_TYPE == UNIT_TYPE_21MX) dat = DMASK;
 
1974
        if (UNIT_CPU_TYPE == UNIT_TYPE_1000)
 
1975
            dat = DMASK;
1777
1976
        break;
1778
1977
 
1779
1978
    case ioOTX:                                         /* output */
1780
 
        dmac[ch].cw1 = dat;
 
1979
        if (UNIT_CPU_MODEL == UNIT_2114)                /* 12607? */
 
1980
            dmac[ch].cw1 = (dat & 0137707) | 010;       /* mask SC, convert to 10-17 */
 
1981
        else if (UNIT_CPU_TYPE == UNIT_TYPE_211X)       /* 12578? */
 
1982
            dmac[ch].cw1 = dat;                         /* store full select code, flags */
 
1983
        else                                            /* 12895, 12897 */
 
1984
            dmac[ch].cw1 = dat & ~DMA1_PB;              /* clip byte-packing flag */
1781
1985
        break;
1782
1986
 
 
1987
    case ioCRS:                                         /* control reset */
 
1988
        clrCMD (DMA0 + ch);                             /* clear command flip-flop */
 
1989
 
1783
1990
    case ioCTL:                                         /* control */
1784
1991
        if (IR & I_CTL) { clrCTL (DMA0 + ch); }         /* CLC: cmd unchgd */
1785
1992
        else {                                          /* STC */
 
1993
            if (UNIT_CPU_TYPE == UNIT_TYPE_211X)        /* slow DMA card? */
 
1994
                dmac[ch].latency = 1;                   /* needs startup latency */
 
1995
            else
 
1996
                dmac[ch].latency = 0;                   /* DCPC starts immediately */
 
1997
 
 
1998
            dmac[ch].packer = 0;                        /* clear packing register */
1786
1999
            setCTL (DMA0 + ch);                         /* set ctl, cmd */
1787
2000
            setCMD (DMA0 + ch);
1788
2001
            }
1798
2011
 
1799
2012
/* DMA cycle routine
1800
2013
 
 
2014
   The 12578A card supports byte-packing.  If bit 14 in control word 1 is set,
 
2015
   each transfer will involve one read/write from memory and two output/input
 
2016
   operations in order to transfer sequential bytes to/from the device.
 
2017
 
1801
2018
   The last cycle (word count reaches 0) logic is quite tricky.
1802
2019
   Input cases:
1803
2020
   - CLC requested: issue CLC
1813
2030
{
1814
2031
int32 temp, dev, MA;
1815
2032
int32 inp = dmac[ch].cw2 & DMA2_OI;                     /* input flag */
 
2033
int32 byt = dmac[ch].cw1 & DMA1_PB;                     /* pack bytes flag */
 
2034
 
 
2035
if (dmac[ch].latency) {                                 /* start-up latency? */
 
2036
    dmac[ch].latency = dmac[ch].latency - 1;            /* decrease it */
 
2037
    return;                                             /* that's all this cycle */
 
2038
    }
1816
2039
 
1817
2040
dev = dmac[ch].cw1 & I_DEVMASK;                         /* get device */
1818
2041
MA = dmac[ch].cw2 & VAMASK;                             /* get mem addr */
1819
 
if (inp) {                                              /* input? */
 
2042
 
 
2043
if (inp) {                                              /* input cycle? */
1820
2044
    temp = devdisp (dev, ioLIX, dev, 0);                /* do LIA dev */
1821
 
    WriteIO (MA, temp, map);                            /* store data */
 
2045
 
 
2046
    if (byt) {                                          /* byte packing? */
 
2047
        if (dmac[ch].packer & DMA_OE) {                 /* second byte? */
 
2048
            temp = (dmac[ch].packer << 8) |             /* merge stored byte */
 
2049
                   (temp & DMASK8);
 
2050
            WriteIO (MA, temp, map);                    /* store word data */
 
2051
            }
 
2052
        else                                            /* first byte */
 
2053
            dmac[ch].packer = (temp & DMASK8);          /* save it */
 
2054
 
 
2055
        dmac[ch].packer = dmac[ch].packer ^ DMA_OE;     /* flip odd/even bit */
 
2056
        }
 
2057
    else                                                /* no byte packing */
 
2058
        WriteIO (MA, temp, map);                        /* store word data */
1822
2059
    }
1823
 
else {
1824
 
    temp = ReadIO (MA, map);                            /* read data */
 
2060
else {                                                  /* output cycle */
 
2061
    if (byt) {                                          /* byte packing? */
 
2062
        if (dmac[ch].packer & DMA_OE)                   /* second byte? */
 
2063
            temp = dmac[ch].packer & DMASK8;            /* retrieve it */
 
2064
 
 
2065
        else {                                          /* first byte */
 
2066
            dmac[ch].packer = ReadIO (MA, map);         /* read word data */
 
2067
            temp = (dmac[ch].packer >> 8) & DMASK8;     /* get high byte */
 
2068
            }
 
2069
 
 
2070
        dmac[ch].packer = dmac[ch].packer ^ DMA_OE;     /* flip odd/even bit */
 
2071
        }
 
2072
    else                                                /* no byte packing */
 
2073
        temp = ReadIO (MA, map);                        /* read word data */
 
2074
 
1825
2075
    devdisp (dev, ioOTX, dev, temp);                    /* do OTA dev */
1826
2076
    }
1827
 
dmac[ch].cw2 = (dmac[ch].cw2 & DMA2_OI) | ((dmac[ch].cw2 + 1) & VAMASK);
1828
 
dmac[ch].cw3 = (dmac[ch].cw3 + 1) & DMASK;              /* incr wcount */
 
2077
 
 
2078
if ((dmac[ch].packer & DMA_OE) == 0) {                  /* new byte or no packing? */
 
2079
    dmac[ch].cw2 = (dmac[ch].cw2 & DMA2_OI) |           /* increment address */
 
2080
                   ((dmac[ch].cw2 + 1) & VAMASK);
 
2081
    dmac[ch].cw3 = (dmac[ch].cw3 + 1) & DMASK;          /* increment word count */
 
2082
    }
 
2083
 
1829
2084
if (dmac[ch].cw3) {                                     /* more to do? */
1830
2085
    if (dmac[ch].cw1 & DMA1_STC)                        /* if STC flag, */
1831
2086
        devdisp (dev, ioCTL, I_HC + dev, 0);            /* do STC,C dev */
1853
2108
 
1854
2109
/* Unimplemented device routine
1855
2110
 
1856
 
   NOTE: For SC < 10, LIx/MIx reads floating S-bus (-1 on 21MX, 0 on 2116/2100).
1857
 
         For SC >= 10, LIx/MIx reads floating I/O bus (0 on all machines). */
 
2111
   NOTE: For SC < 10, LIx/MIx reads floating S-bus (-1 on 21MX, 0 on 211x/2100).
 
2112
         For SC >= 10, LIx/MIx reads floating I/O bus (0 on all machines).
 
2113
*/
1858
2114
 
1859
2115
int32 nulio (int32 inst, int32 IR, int32 dat)
1860
2116
{
1871
2127
        dat = 0;
1872
2128
 
1873
2129
    case ioMIX:                                         /* merge */
1874
 
        if ((devd < VARDEV) && (UNIT_CPU_TYPE == UNIT_TYPE_21MX))
 
2130
        if ((devd < VARDEV) && (UNIT_CPU_TYPE == UNIT_TYPE_1000))
1875
2131
            dat = DMASK;
1876
2132
        break;
1877
2133
 
1900
2156
pcq_r = find_reg ("PCQ", NULL, dptr);
1901
2157
sim_brk_types = ALL_BKPTS;
1902
2158
sim_brk_dflt = SWMASK ('E');
1903
 
if (M == NULL) M = calloc (PASIZE, sizeof (uint16));
1904
 
if (M == NULL) return SCPE_MEM;
 
2159
 
 
2160
if (M == NULL) {                                        /* initial call? */
 
2161
    M = calloc (PASIZE, sizeof (uint16));               /* alloc mem */
 
2162
 
 
2163
    if (M == NULL)                                      /* alloc fail? */
 
2164
        return SCPE_MEM;
 
2165
    else {                                              /* do one-time init */
 
2166
        MEMSIZE = 32768;                                /* set initial memory size */
 
2167
        cpu_set_model (NULL, UNIT_2116, NULL, NULL);    /* set initial CPU model */
 
2168
        SR = 001000;                                    /* select PTR boot ROM at SC 10 */
 
2169
        cpu_boot (0, NULL);                             /* install loader for 2116 */
 
2170
        cpu_set_ldr (NULL, FALSE, NULL, NULL);          /* disable loader (was enabled) */
 
2171
        SR = 0;                                         /* clear S */
 
2172
        sim_vm_post = &hp_post_cmd;                     /* set cmd post proc */
 
2173
        }
 
2174
}
 
2175
 
1905
2176
if (pcq_r) pcq_r->qptr = 0;
1906
2177
else return SCPE_IERR;
1907
 
sim_vm_post = &hp_post_cmd;                             /* set cmd post proc */
1908
2178
return SCPE_OK;
1909
2179
}
1910
2180
 
1922
2192
 
1923
2193
t_stat dma0_reset (DEVICE *tptr)
1924
2194
{
1925
 
hp_enbdis_pair (&dma0_dev, &dma1_dev);                  /* make pair cons */
 
2195
if (UNIT_CPU_MODEL != UNIT_2114)                        /* 2114 has only one channel */
 
2196
    hp_enbdis_pair (&dma0_dev, &dma1_dev);              /* make pair cons */
1926
2197
clrCMD (DMA0);
1927
2198
clrCTL (DMA0);
1928
2199
setFLG (DMA0);
1929
2200
clrSRQ (DMA0);
1930
2201
clrCTL (DMALT0);
 
2202
dmac[0].latency = dmac[0].packer = 0;
1931
2203
if (sim_switches & SWMASK ('P'))                        /* power up? */
1932
2204
    dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0;
1933
2205
return SCPE_OK;
1935
2207
 
1936
2208
t_stat dma1_reset (DEVICE *tptr)
1937
2209
{
1938
 
hp_enbdis_pair (&dma1_dev, &dma0_dev);                  /* make pair cons */
 
2210
if (UNIT_CPU_MODEL != UNIT_2114)                        /* 2114 has only one channel */
 
2211
    hp_enbdis_pair (&dma1_dev, &dma0_dev);              /* make pair cons */
1939
2212
clrCMD (DMA1);
1940
2213
clrCTL (DMA1);
1941
2214
setFLG (DMA1);
1942
2215
clrSRQ (DMA1);
1943
2216
clrCTL (DMALT1);
 
2217
dmac[1].latency = dmac[1].packer = 0;
1944
2218
if (sim_switches & SWMASK ('P'))                        /* power up? */
1945
2219
    dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0;
1946
2220
return SCPE_OK;
1973
2247
return SCPE_OK;
1974
2248
}
1975
2249
 
1976
 
/* Memory size validation */
1977
 
 
1978
 
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
1979
 
{
1980
 
int32 mc = 0;
1981
 
uint32 i;
1982
 
 
1983
 
if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) ||
1984
 
    ((UNIT_CPU_TYPE != UNIT_TYPE_21MX) && (val > VASIZE)))
1985
 
    return SCPE_ARG;
1986
 
if (!(sim_switches & SWMASK ('F'))) {                   /* force truncation? */
1987
 
    for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
1988
 
    if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
1989
 
        return SCPE_INCOMP;
1990
 
        }
1991
 
MEMSIZE = val;
1992
 
for (i = MEMSIZE; i < PASIZE; i++) M[i] = 0;
1993
 
return SCPE_OK;
1994
 
}
1995
 
 
1996
2250
/* Set device number */
1997
2251
 
1998
2252
t_stat hp_setdev (UNIT *uptr, int32 num, char *cptr, void *desc)
2038
2292
return;
2039
2293
}
2040
2294
 
2041
 
/* Command post-processor
 
2295
/* VM command post-processor
2042
2296
 
2043
 
   Update T register to contents of memory addressed by M register. */
 
2297
   Update T register to contents of memory addressed by M register
 
2298
   if M register has changed. */
2044
2299
 
2045
2300
void hp_post_cmd (t_bool from_scp)
2046
2301
{
2047
 
TR = ReadTAB (MR);                                      /* sync T with M */
 
2302
if (MR != saved_MR) {                                   /* M changed since last update? */
 
2303
    saved_MR = MR;
 
2304
    TR = ReadTAB (MR);                                  /* sync T with new M */
 
2305
    }
2048
2306
return;
2049
2307
}
2050
2308
 
2095
2353
return is_conflict;
2096
2354
}
2097
2355
 
2098
 
/* Configuration validation
2099
 
 
2100
 
   - Checks that the current CPU type supports the option selected.
2101
 
   - Ensures that FP/FFP and IOP are mutually exclusive if CPU is 2100.
2102
 
   - Disables memory protect if 2116 is selected.
2103
 
   - Enables memory protect if 2100 or 21MX or DMS is selected.
2104
 
   - Enables DMA if 2116 or 2100 or 21MX is selected.
2105
 
   - Memory is trimmed to 32K if 2116 or 2100 is selected. */
2106
 
 
2107
 
t_bool cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
2108
 
{
2109
 
int32 opt = (int32) desc;
 
2356
/* Change CPU memory size.
 
2357
 
 
2358
   On a 21xx, move the current loader to the top of the new memory size.  Then
 
2359
   clear "non-existent memory" so that reads return zero, per spec.
 
2360
 
 
2361
   Validation:
 
2362
   - New size <= maximum size for current CPU.
 
2363
   - New size a positive multiple of 4K (progamming error if not).
 
2364
   - If new size < old size, truncation accepted.
 
2365
*/
 
2366
 
 
2367
t_stat cpu_set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc)
 
2368
{
 
2369
int32 mc = 0;
 
2370
uint32 i;
 
2371
uint32 model = CPU_MODEL_INDEX;                         /* current CPU model index */
 
2372
uint32 old_size = MEMSIZE;                              /* current memory size */
 
2373
 
 
2374
if ((uint32) new_size > cpu_features[model].maxmem)
 
2375
    return SCPE_NOFNC;                                  /* mem size unsupported */
 
2376
 
 
2377
if ((new_size <= 0) || (new_size > PASIZE) || ((new_size & 07777) != 0))
 
2378
    return SCPE_NXM;                                    /* invalid size (prog err) */
 
2379
 
 
2380
if (!(sim_switches & SWMASK ('F'))) {                   /* force truncation? */
 
2381
    for (i = new_size; i < MEMSIZE; i++) mc = mc | M[i];
 
2382
    if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
 
2383
        return SCPE_INCOMP;
 
2384
        }
 
2385
 
 
2386
if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) {              /* 21xx CPU? */
 
2387
    cpu_set_ldr (uptr, FALSE, NULL, NULL);              /* save loader to shadow RAM */
 
2388
    MEMSIZE = new_size;                                 /* set new memory size */
 
2389
    fwanxm = MEMSIZE - IBL_LNT;                         /* reserve memory for loader */
 
2390
    }
 
2391
else                                                    /* loader unsupported */
 
2392
    fwanxm = MEMSIZE = new_size;                        /* set new memory size */
 
2393
 
 
2394
for (i = fwanxm; i < old_size; i++) M[i] = 0;           /* zero non-existent memory */
 
2395
return SCPE_OK;
 
2396
}
 
2397
 
 
2398
/* Change CPU models.
 
2399
 
 
2400
   For convenience, MP and DMA are typically enabled if available; they may be
 
2401
   disabled subsequently if desired.  Note that the 2114 supports only one DMA
 
2402
   channel (channel 0).  All other models support two channels.
 
2403
 
 
2404
   Validation:
 
2405
   - Sets standard equipment and convenience features.
 
2406
   - Changes DMA device name to DCPC if 1000 is selected.
 
2407
   - Enforces maximum memory allowed (doesn't change otherwise).
 
2408
   - Disables loader on 21xx machines.
 
2409
*/
 
2410
 
 
2411
t_stat cpu_set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc)
 
2412
{
 
2413
uint32 old_family = UNIT_CPU_FAMILY;                    /* current CPU type */
 
2414
uint32 new_family = new_model & UNIT_FAMILY_MASK;       /* new CPU family */
 
2415
uint32 new_index  = new_model >> UNIT_V_CPU;            /* new CPU model index */
 
2416
uint32 new_memsize;
 
2417
t_stat result;
 
2418
 
 
2419
cpu_unit.flags = cpu_unit.flags & ~UNIT_OPTS |          /* set typical features */
 
2420
                 cpu_features[new_index].typ & UNIT_OPTS;   /* mask pseudo-opts */
 
2421
 
 
2422
 
 
2423
if (cpu_features[new_index].typ & UNIT_MP)              /* MP in typ config? */
 
2424
    mp_dev.flags = mp_dev.flags & ~DEV_DIS;             /* enable it */
 
2425
else
 
2426
    mp_dev.flags = mp_dev.flags |  DEV_DIS;             /* disable it */
 
2427
 
 
2428
if (cpu_features[new_index].opt & UNIT_MP)              /* MP an option? */
 
2429
    mp_dev.flags = mp_dev.flags |  DEV_DISABLE;         /* make it alterable */
 
2430
else
 
2431
    mp_dev.flags = mp_dev.flags & ~DEV_DISABLE;         /* make it unalterable */
 
2432
 
 
2433
 
 
2434
if (cpu_features[new_index].typ & UNIT_DMA) {           /* DMA in typ config? */
 
2435
    dma0_dev.flags = dma0_dev.flags & ~DEV_DIS;         /* enable DMA channel 0 */
 
2436
 
 
2437
    if (new_model == UNIT_2114)                         /* 2114 has only one channel */
 
2438
        dma1_dev.flags = dma1_dev.flags |  DEV_DIS;     /* disable channel 1 */
 
2439
    else                                                /* all others have two channels */
 
2440
        dma1_dev.flags = dma1_dev.flags & ~DEV_DIS;     /* enable it */
 
2441
    }
 
2442
else {
 
2443
    dma0_dev.flags = dma0_dev.flags | DEV_DIS;          /* disable channel 0 */
 
2444
    dma1_dev.flags = dma1_dev.flags | DEV_DIS;          /* disable channel 1 */
 
2445
    }
 
2446
 
 
2447
if (cpu_features[new_index].opt & UNIT_DMA) {           /* DMA an option? */
 
2448
    dma0_dev.flags = dma0_dev.flags |  DEV_DISABLE;     /* make it alterable */
 
2449
 
 
2450
    if (new_model == UNIT_2114)                         /* 2114 has only one channel */
 
2451
        dma1_dev.flags = dma1_dev.flags & ~DEV_DISABLE; /* make it unalterable */
 
2452
    else                                                /* all others have two channels */
 
2453
        dma1_dev.flags = dma1_dev.flags |  DEV_DISABLE; /* make it alterable */
 
2454
    }
 
2455
else {
 
2456
    dma0_dev.flags = dma0_dev.flags & ~DEV_DISABLE;     /* make it unalterable */
 
2457
    dma1_dev.flags = dma1_dev.flags & ~DEV_DISABLE;     /* make it unalterable */
 
2458
    }
 
2459
 
 
2460
 
 
2461
if ((old_family == UNIT_FAMILY_1000) &&                 /* if current family is 1000 */
 
2462
    (new_family == UNIT_FAMILY_21XX)) {                 /* and new family is 21xx */
 
2463
    deassign_device (&dma0_dev);                        /* delete DCPC names */
 
2464
    deassign_device (&dma1_dev);
 
2465
    }
 
2466
else if ((old_family == UNIT_FAMILY_21XX) &&            /* if current family is 21xx */
 
2467
         (new_family == UNIT_FAMILY_1000)) {            /* and new family is 1000 */
 
2468
    assign_device (&dma0_dev, "DCPC0");                 /* change DMA device name */
 
2469
    assign_device (&dma1_dev, "DCPC1");                 /* to DCPC for familiarity */
 
2470
    }
 
2471
 
 
2472
if ((MEMSIZE == 0) ||                                   /* current mem size not set? */
 
2473
    (MEMSIZE > cpu_features[new_index].maxmem))         /* current mem size too large? */
 
2474
    new_memsize = cpu_features[new_index].maxmem;       /* set it to max supported */
 
2475
else
 
2476
    new_memsize = MEMSIZE;                              /* or leave it unchanged */
 
2477
 
 
2478
result = cpu_set_size (uptr, new_memsize, NULL, NULL);  /* set memory size */
 
2479
 
 
2480
if (result == SCPE_OK)                                  /* memory change OK? */
 
2481
    if (new_family == UNIT_FAMILY_21XX)                 /* 21xx CPU? */
 
2482
        fwanxm = MEMSIZE - IBL_LNT;                     /* reserve memory for loader */
 
2483
    else
 
2484
        fwanxm = MEMSIZE;                               /* loader reserved only for 21xx */
 
2485
 
 
2486
return result;
 
2487
}
 
2488
 
 
2489
/* Display the CPU model and optional loader status.
 
2490
 
 
2491
   Loader status is displayed for 21xx models and suppressed for 1000 models.
 
2492
*/
 
2493
 
 
2494
t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc)
 
2495
{
 
2496
fputs ((char *) desc, st);                              /* write model name */
 
2497
 
 
2498
if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX)                /* valid only for 21xx */
 
2499
    if (fwanxm < MEMSIZE)                               /* loader area non-existent? */
 
2500
        fputs (", loader disabled", st);                /* yes, so access disabled */
 
2501
    else
 
2502
        fputs (", loader enabled", st);                 /* no, so access enabled */
 
2503
return SCPE_OK;
 
2504
}
 
2505
 
 
2506
/* Set a CPU option.
 
2507
 
 
2508
   Validation:
 
2509
   - Checks that the current CPU model supports the option selected.
 
2510
   - If CPU is 2100, ensures that FP/FFP and IOP are mutually exclusive.
 
2511
   - If CPU is 2100, ensures that FP is enabled if FFP enabled
 
2512
     (FP is required for FFP installation).
 
2513
*/
 
2514
 
 
2515
t_stat cpu_set_opt (UNIT *uptr, int32 option, char *cptr, void *desc)
 
2516
{
 
2517
uint32 model = CPU_MODEL_INDEX;                         /* current CPU model index */
 
2518
 
 
2519
if ((cpu_features[model].opt & option) == 0)            /* option supported? */
 
2520
    return SCPE_NOFNC;                                  /* no */
 
2521
 
 
2522
if (UNIT_CPU_TYPE == UNIT_TYPE_2100) {
 
2523
    if ((option == UNIT_FP) || (option == UNIT_FFP))    /* 2100 IOP and FP/FFP options */
 
2524
        uptr->flags = uptr->flags & ~UNIT_IOP;          /* are mutually exclusive */
 
2525
    else if (option == UNIT_IOP)
 
2526
        uptr->flags = uptr->flags & ~(UNIT_FP | UNIT_FFP);
 
2527
 
 
2528
    if (option == UNIT_FFP)                             /* 2100 FFP option requires FP */
 
2529
        uptr->flags = uptr->flags | UNIT_FP;
 
2530
    }
 
2531
 
 
2532
return SCPE_OK;
 
2533
}
 
2534
 
 
2535
/* Clear a CPU option.
 
2536
 
 
2537
   Validation:
 
2538
   - Checks that the current CPU model supports the option selected.
 
2539
   - Clears flag from unit structure (we are processing MTAB_XTD entries).
 
2540
   - If CPU is 2100, ensures that FFP is disabled if FP disabled
 
2541
     (FP is required for FFP installation).
 
2542
*/
 
2543
 
 
2544
t_bool cpu_clr_opt (UNIT *uptr, int32 option, char *cptr, void *desc)
 
2545
{
 
2546
uint32 model = CPU_MODEL_INDEX;                         /* current CPU model index */
 
2547
 
 
2548
if ((cpu_features[model].opt & option) == 0)            /* option supported? */
 
2549
    return SCPE_NOFNC;                                  /* no */
 
2550
 
 
2551
uptr->flags = uptr->flags & ~option;                    /* disable option */
 
2552
 
 
2553
if ((UNIT_CPU_TYPE == UNIT_TYPE_2100) &&                /* disabling 2100 FP? */
 
2554
    (option == UNIT_FP))
 
2555
    uptr->flags = uptr->flags & ~UNIT_FFP;              /* yes, so disable FFP too */
 
2556
 
 
2557
return SCPE_OK;
 
2558
}
 
2559
 
 
2560
/* 21xx loader enable/disable function.
 
2561
 
 
2562
   The 21xx CPUs store their initial binary loaders in the last 64 words of
 
2563
   available memory.  This memory is protected by a LOADER ENABLE switch on the
 
2564
   front panel.  When the switch is off (disabled), main memory effectively ends
 
2565
   64 locations earlier, i.e., the loader area is treated as non-existent.
 
2566
   Because these are core machines, the loader is retained when system power is
 
2567
   off.
 
2568
 
 
2569
   1000 CPUs do not have a protected loader feature.  Instead, loaders are
 
2570
   stored in PROMs and are copied into main memory for execution by the IBL
 
2571
   switch.
 
2572
 
 
2573
   Under simulation, we keep both a total configured memory size (MEMSIZE) and a
 
2574
   current configured memory size (fwanxm = "first word address of non-existent
 
2575
   memory).  When the two are equal, the loader is enabled.  When the current
 
2576
   size is less than the total size, the loader is disabled.
 
2577
 
 
2578
   Disabling the loader copies the last 64 words to a shadow array, zeros the
 
2579
   corresponding memory, and decreases the last word of addressable memory by
 
2580
   64.  Enabling the loader reverses this process.
 
2581
 
 
2582
   Disabling may be done manually by user command or automatically when a halt
 
2583
   instruction is executed.  Enabling occurs only by user command.  This differs
 
2584
   slightly from actual machine operation, which additionally disables the
 
2585
   loader when a manual halt is performed.  We do not do this to allow
 
2586
   breakpoints within and single-stepping through the loaders.
 
2587
*/
 
2588
 
 
2589
t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc)
 
2590
{
 
2591
static uint16 loader[IBL_LNT];
2110
2592
int32 i;
2111
 
uint32 mod;
2112
 
 
2113
 
mod = MOD_CURRENT;
2114
 
for (i = 0; opt_val[i].cpuf != 0; i++) {
2115
 
    if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) {
2116
 
        if (mod == MOD_2100)
2117
 
            if ((opt == UNIT_FP) || (opt == UNIT_FFP))
2118
 
                uptr->flags = uptr->flags & ~UNIT_IOP;
2119
 
            else if (opt == UNIT_IOP)
2120
 
                uptr->flags = uptr->flags & ~(UNIT_FP | UNIT_FFP);
2121
 
        if (opt == TYPE_211X)
2122
 
            mp_dev.flags = mp_dev.flags | DEV_DIS;
2123
 
        else if ((opt == UNIT_DMS) || (opt == TYPE_2100) || (opt == TYPE_21MX))
2124
 
            mp_dev.flags = mp_dev.flags & ~DEV_DIS;
2125
 
        if ((opt == TYPE_211X) || (opt == TYPE_2100) || (opt == TYPE_21MX)) {
2126
 
            dma0_dev.flags = dma0_dev.flags & ~DEV_DIS;
2127
 
            dma1_dev.flags = dma1_dev.flags & ~DEV_DIS;
2128
 
            }
2129
 
        if (((opt == TYPE_211X) || (opt == TYPE_2100)) && (MEMSIZE > VASIZE))
2130
 
            return cpu_set_size (uptr, VASIZE, cptr, desc);
2131
 
        return SCPE_OK;
 
2593
t_bool is_enabled = (fwanxm == MEMSIZE);
 
2594
 
 
2595
if ((UNIT_CPU_FAMILY != UNIT_FAMILY_21XX) ||            /* valid only for 21xx */
 
2596
    (MEMSIZE == 0))                                     /* and for initialized memory */
 
2597
    return SCPE_NOFNC;
 
2598
 
 
2599
if (is_enabled && (enable == 0)) {                      /* disable loader? */
 
2600
    fwanxm = MEMSIZE - IBL_LNT;                         /* decrease available memory */
 
2601
    for (i = 0; i < IBL_LNT; i++) {                     /* copy loader */
 
2602
        loader[i] = M[fwanxm + i];                      /* from memory */
 
2603
        M[fwanxm + i] = 0;                              /* and zero location */
2132
2604
        }
2133
2605
    }
2134
 
return SCPE_NOFNC;
 
2606
 
 
2607
else if ((!is_enabled) && (enable == 1)) {              /* enable loader? */
 
2608
    for (i = 0; i < IBL_LNT; i++)                       /* copy loader */
 
2609
        M[fwanxm + i] = loader[i];                      /* to memory */
 
2610
    fwanxm = MEMSIZE;                                   /* increase available memory */
 
2611
    }
 
2612
 
 
2613
return SCPE_OK;
2135
2614
}
2136
2615
 
2137
2616
/* IBL routine (CPU boot) */
2183
2662
int32 i;
2184
2663
uint16 wd;
2185
2664
 
 
2665
cpu_set_ldr (NULL, TRUE, NULL, NULL);                   /* enable loader (ignore errors) */
 
2666
 
2186
2667
if (dev < 010) return SCPE_ARG;                         /* valid device? */
2187
2668
PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK;              /* start at mem top */
2188
2669
for (i = 0; i < IBL_LNT; i++) {                         /* copy bootstrap */
2197
2678
M[PC + IBL_END] = (~PC + 1) & DMASK;                    /* fill in start of boot */
2198
2679
return SCPE_OK;
2199
2680
}
2200