blob: b075dd0ac922e1213c6825d4f652b94e39697eec [file] [log] [blame] [raw]
/* i701_cpu.c: IBM 701 CPU simulator
Copyright (c) 2005-2016, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cpu 701 central processor
The IBM 701 also know as "Defense Calculator" was introduced by IBM
on April 7, 1953. This computer was start of IBM 700 and 7000 line.
Memory was 2048 36 bit words. Each instruction could be signed plus
or minus, plus would access memory as 18 bit words, minus as 36 bit
words. There was a expansion option to add another 2048 words of
memory, but I can't find documentation on how it worked. Memory cycle
time was 12 microseconds. The 701 was withdrawn from the market
October 1, 1954 replaced by 704 and 702. A total of 19 machines were
installed.
The system state for the IBM 701 is:
AC<S,P,Q,1:35> AC register
MQ<S,1:35> MQ register
IC<0:15> program counter
SSW<0:5> sense switches
SLT<0:3> sense lights
ACOVF AC overflow
DVC divide check
IOC I/O check
The 701 had one instruction format: memory reference,
00000 000011111111
S 12345 678901234567
+-+-----+------------+
| |opcod| address | memory reference
+-+-----+------------+
This routine is the instruction decode routine for the 701.
It is called from the simulator control program to execute
instructions in simulated memory, starting at the simulated PC.
It runs until a stop condition occurs.
General notes:
1. Reasons to stop. The simulator can be stopped by:
HALT instruction
illegal instruction
illegal I/O operation for device
illegal I/O operation for channel
breakpoint encountered
nested XEC's exceeding limit
divide check
I/O error in I/O simulator
3. Arithmetic. The 701 uses signed magnitude arithmetic for
integer and floating point calculations, and 2's complement
arithmetic for indexing calculations.
4. Adding I/O devices. These modules must be modified:
i7090_defs.h add device definitions
i7090_chan.c add channel subsystem
i701_sys.c add sim_devices table entry
*/
#include "i7090_defs.h"
#define HIST_XCT 1 /* instruction */
#define HIST_INT 2 /* interrupt cycle */
#define HIST_TRP 3 /* trap cycle */
#define HIST_MIN 64
#define HIST_MAX 65536
#define HIST_NOEA 0x40000000
#define HIST_PC 0x10000
struct InstHistory
{
t_int64 ac;
t_int64 mq;
t_int64 op;
t_int64 sr;
uint32 ic;
uint16 ea;
};
t_stat cpu_ex(t_value * vptr, t_addr addr, UNIT * uptr,
int32 sw);
t_stat cpu_dep(t_value val, t_addr addr, UNIT * uptr,
int32 sw);
t_stat cpu_reset(DEVICE * dptr);
t_stat cpu_set_size(UNIT * uptr, int32 val, CONST char *cptr,
void *desc);
t_stat cpu_show_hist(FILE * st, UNIT * uptr, int32 val,
CONST void *desc);
t_stat cpu_set_hist(UNIT * uptr, int32 val, CONST char *cptr,
void *desc);
t_stat cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
const char *cptr);
const char *cpu_description (DEVICE *dptr);
t_uint64 M[MAXMEMSIZE] = { 0 }; /* memory */
t_uint64 AC, MQ; /* registers */
uint16 IC; /* program counter */
uint8 SL; /* Sense lights */
uint8 SW = 0; /* Sense switch */
uint8 dcheck; /* Divide check */
uint8 acoflag; /* AC Overflow */
uint8 ihold = 0; /* Hold interrupts */
uint16 iotraps; /* IO trap flags */
t_uint64 ioflags; /* Trap enable flags */
uint8 iocheck;
uint8 iowait; /* Waiting on io */
uint8 dualcore; /* Set to true if dual core in
use */
uint16 dev_pulse[NUM_CHAN]; /* SPRA device pulses */
int cycle_time = 120; /* Cycle time of 12us */
/* History information */
int32 hst_p = 0; /* History pointer */
int32 hst_lnt = 0; /* History length */
struct InstHistory *hst = NULL; /* History stack */
extern uint32 drum_addr;
uint32 hsdrm_addr;
extern UNIT chan_unit[];
#undef AMASK /* Change definition of AMASK here */
#define AMASK 00000000007777L
/* CPU data structures
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_BINK, MAXMEMSIZE / 2) };
REG cpu_reg[] = {
{ORDATAD(IC, IC, 15, "Instruction counter"), REG_FIT},
{ORDATAD(AC, AC, 38, "Accumulator"), REG_FIT},
{ORDATAD(MQ, MQ, 36, "Multiplier quotent"), REG_FIT},
{ORDATAD(SL, SL, 4, "Lights"), REG_FIT},
{ORDATAD(SW, SW, 6, "Switch register"), REG_FIT},
{FLDATAD(SW1, SW, 0, "Switch 0"), REG_FIT},
{FLDATAD(SW2, SW, 1, "Switch 1"), REG_FIT},
{FLDATAD(SW3, SW, 2, "Switch 2"), REG_FIT},
{FLDATAD(SW4, SW, 3, "Switch 3"), REG_FIT},
{FLDATAD(SW5, SW, 4, "Switch 4"), REG_FIT},
{FLDATAD(SW6, SW, 5, "Switch 5"), REG_FIT},
{ORDATAD(ACOVF, acoflag, 1, "Overflow flag"), REG_FIT},
{ORDATAD(IOC, iocheck, 1, "I/O Check flag"), REG_FIT},
{ORDATAD(DVC, dcheck, 1, "Divide Check"), REG_FIT},
{NULL}
};
MTAB cpu_mod[] = {
{MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist},
{0}
};
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 8, 15, 1, 8, 36,
&cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL,
NULL, 0, 0, NULL,
NULL, NULL, &cpu_help, NULL, NULL, &cpu_description
};
/* Simulate instructions */
t_stat
sim_instr(void)
{
t_stat reason;
t_uint64 temp = 0;
t_uint64 ibr;
t_uint64 SR;
uint16 opcode;
uint16 MA;
uint8 f;
int shiftcnt;
int stopnext = 0;
int instr_count = 0; /* Number of instructions to execute */
if (sim_step != 0) {
instr_count = sim_step;
sim_cancel_step();
}
reason = 0;
iowait = 0;
while (reason == 0) { /* loop until halted */
/* If doing fast I/O don't sit in idle loop */
if (iowait == 0 && stopnext)
return SCPE_STEP;
if (sim_interval <= 0) { /* event queue? */
reason = sim_process_event();
if (reason != SCPE_OK) {
if (reason == SCPE_STEP && iowait)
stopnext = 1;
else
break; /* process */
}
}
if (iowait == 0 && sim_brk_summ && sim_brk_test(IC, SWMASK('E'))) {
reason = STOP_IBKPT;
break;
}
/* Split out current instruction */
if (iowait) {
/* If we are awaiting I/O complete, don't fetch. */
sim_interval -= 6;
iowait = 0;
} else {
MA = IC >> 1;
sim_interval -= 24; /* count down */
SR = ReadP(MA);
temp = SR;
if ((IC & 1) == 0)
temp >>= 18;
if (hst_lnt) { /* history enabled? */
hst_p = (hst_p + 1); /* next entry */
if (hst_p >= hst_lnt)
hst_p = 0;
hst[hst_p].ic = IC | HIST_PC;
hst[hst_p].ea = 0;
hst[hst_p].op = temp & RMASK;
hst[hst_p].ac = AC;
hst[hst_p].mq = MQ;
hst[hst_p].sr = 0;
}
IC = (IC + 1) & AMASK;
}
ihold = 0;
opcode = ((uint16)(temp >> 12L)) & 077;
MA = (uint16)(temp & AMASK);
ibr = SR = ReadP(MA>>1);
if ((opcode & 040) == 0) {
if (MA & 1)
SR <<= 18;
SR &= LMASK;
}
if (hst_lnt) { /* history enabled? */
hst[hst_p].sr = SR;
hst[hst_p].ea = MA;
}
switch (opcode & 037) {
case 19: /* RND */
if (MQ & ONEBIT)
AC++;
break;
case 30: /* SENSE */
switch (MA) {
case 64: /* SLN */
SL = 0;
break;
case 65: /* */
SL |= 1;
break;
case 66:
SL |= 2;
break;
case 67:
SL |= 4;
break;
case 68:
SL |= 8;
break;
case 69:
if ((SW & 1) == 0)
IC++;
break;
case 70:
if ((SW & 2) == 0)
IC++;
break;
case 71:
if ((SW & 4) == 0)
IC++;
break;
case 72:
if ((SW & 8) == 0)
IC++;
break;
case 73:
if ((SW & 16) == 0)
IC++;
break;
case 74:
if ((SW & 32) == 0)
IC++;
break;
case 1024:
case 1025:
MA -= 1024;
dev_pulse[0] |= 1 << MA;
break;
case 522:
if (dev_pulse[0] & PRINT_I)
IC++;
dev_pulse[0] &= ~PRINT_I;
break;
case 512:
case 513:
case 514:
case 515:
case 516:
case 517:
case 518:
case 519:
case 520:
case 521:
MA = (MA - 512) + 5;
dev_pulse[0] |= 1 << MA;
break;
}
break;
case 0: /* STOP */
/* Stop at HTR instruction if trapped */
IC--;
halt:
reason = STOP_HALT;
/* Clear off any pending events before we halt */
do {
f = chan_active(0);
chan_proc();
for (shiftcnt = 1; shiftcnt < NUM_CHAN; shiftcnt++) {
f |= chan_active(shiftcnt);
}
sim_interval = 0;
(void)sim_process_event();
} while (f);
if (reason != 0)
IC = MA;
break;
case 8: /* NO OP */
break;
case 1: /* TR */
IC = MA;
break;
case 4: /* TR 0 */
f = (AC & AMMASK) == 0;
branch:
if (f) {
IC = MA;
}
break;
case 2: /* TR OV */
f = acoflag;
acoflag = 0;
goto branch;
case 3: /* TR + */
f = ((AC & AMSIGN) == 0);
goto branch;
case 10: /* R ADD */
AC = ((SR & MSIGN) << 2) | (SR & PMASK);
sim_interval -= 6;
break;
case 6: /* R SUB */
AC = (((SR & MSIGN) ^ MSIGN) << 2) | (SR & PMASK);
sim_interval -= 6;
break;
case 15: /* LOAD MQ */
MQ = SR;
sim_interval -= 6;
break;
case 14: /* STORE MQ */
SR = MQ;
goto store;
case 12: /* STORE */
SR = AC & PMASK;
if (AC & AMSIGN)
SR |= MSIGN;
store:
if ((opcode & 040) == 0) {
SR &= LMASK;
if (MA & 1) {
ibr &= LMASK;
SR >>= 18;
} else {
ibr &= RMASK;
}
SR |= ibr;
}
WriteP(MA>>1, SR);
if (hst_lnt) { /* history enabled? */
hst[hst_p].sr = SR;
}
sim_interval -= 6;
break;
/* Logic operations */
case 13: /* EXTR or STORE A */
if ((opcode & 040) == 0) {
SR &= ~(AMASK << 18);
SR |= AC & (AMASK << 18);
} else {
t_uint64 t = AC & PMASK;
if (AC & AMSIGN)
t |= MSIGN;
SR &= t;
}
goto store;
case 7: /* SUB AB */
SR |= MSIGN;
goto iadd;
case 11: /* ADD AB */
SR &= PMASK;
goto iadd;
case 5: /* SUB */
SR ^= MSIGN;
/* Fall through */
case 9: /* ADD */
iadd:
f = 0;
/* Make AC Positive */
if (AC & AMSIGN) {
f = 2;
AC &= AMMASK;
}
if (AC & APSIGN)
f |= 8;
/* Check signes of SR & AC */
if (((SR & MSIGN) && ((f & 2) == 0)) ||
(((SR & MSIGN) == 0) && ((f & 2) != 0))) {
AC ^= AMMASK; /* One's compliment */
f |= 1;
}
AC = AC + (SR & PMASK);
/* Check carry from Q */
if (f & 1) { /* Check if signs were not same */
if (AC & AMSIGN) {
f ^= 2;
AC++;
if (((AC & APSIGN) != 0) != ((f & 8) != 0))
acoflag = 1;
} else {
AC ^= AMMASK; /* One's compliment */
}
} else {
if (((AC & APSIGN) != 0) != ((f & 8) != 0))
acoflag = 1;
}
/* Restore sign to AC */
AC &= AMMASK;
if (f & 2)
AC |= AMSIGN;
sim_interval -= 6;
break;
case 16: /* MPY */
case 17: /* MPY R */
shiftcnt = 043;
sim_interval -= 34 * 6;
f = 0;
/* Save sign */
if (MQ & MSIGN)
f |= 1;
if (SR & MSIGN)
f |= 2;
SR &= PMASK;
MQ &= PMASK;
AC = 0; /* Clear AC */
if (SR == 0) {
MQ = 0;
} else {
while (shiftcnt-- > 0) {
if (MQ & 1)
AC += SR;
MQ >>= 1;
if (AC & 1)
MQ |= ONEBIT;
AC >>= 1;
}
}
if ((opcode & 037) == 17 && MQ & ONEBIT)
AC++;
if (f & 2)
f ^= 1;
if (f & 1) {
MQ |= MSIGN;
AC |= AMSIGN;
}
break;
case 18: /* DIV */
shiftcnt = 043;
sim_interval -= 34 * 6;
/* Save sign */
if (SR & MSIGN) {
SR &= PMASK;
f = 1;
} else
f = 0;
if (AC & AMSIGN)
f |= 2;
/* Check if SR less then AC */
if (((SR - (AC & AMMASK)) & AMSIGN) ||
(SR == (AC & AMMASK))) {
dcheck = 1;
MQ &= PMASK;
if (f == 1 || f == 2)
MQ |= MSIGN;
goto halt;
}
/* Clear signs */
MQ &= PMASK;
AC &= AMMASK;
/* Do divide operation */
do {
AC <<= 1;
AC &= AMMASK;
MQ <<= 1;
if (MQ & MSIGN) {
MQ ^= MSIGN;
AC |= 1;
}
if (SR <= AC) {
AC -= SR;
MQ |= 1;
}
} while (--shiftcnt != 0);
switch (f) {
case 0:
break;
case 3:
AC |= AMSIGN;
break;
case 2:
AC |= AMSIGN;
/* FALL THRU */
case 1:
MQ |= MSIGN;
break;
}
break;
/* Shift */
case 20: /* L LEFT */
shiftcnt = MA & 0377;
sim_interval -= (shiftcnt >> 6) * 6;
/* Save sign */
if (MQ & MSIGN)
f = 1;
else
f = 0;
/* Clear it for now */
AC &= AQMASK;
while (shiftcnt-- > 0) {
MQ <<= 1;
AC <<= 1;
if (MQ & MSIGN)
AC |= 1;
if (AC & APSIGN)
acoflag = 1;
}
/* Restore sign when done */
AC &= AMMASK;
MQ &= PMASK;
if (f) {
AC |= AMSIGN;
MQ |= MSIGN;
}
break;
case 21: /* L RIGHT */
shiftcnt = MA & 0377;
sim_interval -= (shiftcnt >> 6) * 6;
/* Save sign */
if (AC & AMSIGN)
f = 1;
else
f = 0;
/* Clear it for now */
AC &= AMMASK;
MQ &= PMASK;
while (shiftcnt-- > 0) {
if (AC & 1)
MQ |= MSIGN;;
MQ >>= 1;
AC >>= 1;
}
/* Restore sign when done */
AC &= AMMASK;
if (f) {
AC |= AMSIGN;
MQ |= MSIGN;
}
break;
case 22: /* A LEFT */
shiftcnt = MA & 0377;
sim_interval -= (shiftcnt >> 6) * 6;
/* Save sign */
if (AC & AMSIGN)
f = 1;
else
f = 0;
/* Clear it for now */
AC &= AQMASK;
while (shiftcnt-- > 0) {
AC <<= 1;
if (AC & APSIGN)
acoflag = 1;
}
/* Restore sign and overflow when done */
AC &= AMMASK;
if (f)
AC |= AMSIGN;
break;
case 23: /* A RIGHT */
shiftcnt = MA & 0377;
sim_interval -= (shiftcnt >> 6) * 6;
/* Save sign */
if (AC & AMSIGN)
f = 1;
else
f = 0;
/* Clear it for now */
AC &= AMMASK;
AC >>= shiftcnt;
/* Restore sign when done */
if (f)
AC |= AMSIGN;
break;
/* 704 Input output Instructions */
case 29: /* SET DR */
if (chan_test(0, DEV_SEL)) {
drum_addr = (uint32)MA;
chan_clear(0, DEV_FULL); /* Incase something got
read while waiting */
} else
iocheck = 1;
break;
case 31: /* COPY */
/* If no channel, set Iocheck and treat as nop */
if (chan_unit[0].flags & UNIT_DIS) {
iocheck = 1;
break;
}
/* If device disconnecting, just wait */
if (chan_test(0, DEV_DISCO)) {
iowait = 1;
break;
}
/* Instruct is NOP first time */
/* Incomplete last word leaves result in MQ */
if (chan_select(0)) {
extern uint8 bcnt[NUM_CHAN];
chan_set(0, STA_ACTIVE);
switch (chan_flags[0] & (DEV_WRITE | DEV_FULL)) {
case DEV_WRITE | DEV_FULL:
case 0:
/* On EOR skip 1, on EOF skip two */
if (chan_test(0, CHS_EOF|CHS_EOT|DEV_REOR))
chan_set(0, DEV_DISCO);
iowait = 1;
break;
case DEV_WRITE:
MQ = assembly[0] = SR;
bcnt[0] = 6;
chan_set(0, DEV_FULL);
break;
case DEV_FULL:
SR = MQ;
WriteP(MA, MQ);
bcnt[0] = 6;
chan_clear(0, DEV_FULL);
break;
}
} else {
if (chan_stat(0, CHS_EOF|CHS_EOT)) {
IC++;
/* On EOR skip two */
} else if (chan_stat(0, DEV_REOR)) {
IC += 2;
/* Advance 1 on Error and set iocheck */
} else if (chan_stat(0, CHS_ERR)) {
iocheck = 1;
IC++;
}
chan_clear(0, STA_ACTIVE|DEV_REOR|CHS_ERR);
break;
}
break;
/* Input/Output Instuctions */
case 24: /* Read select */
opcode = IO_RDS;
MQ = 0;
goto iostart;
case 26: /* Write select */
opcode = IO_WRS;
goto iostart;
case 27: /* Write EOF */
opcode = IO_WEF;
goto iostart;
case 25: /* Read Backwards */
opcode = IO_RDB;
MQ = 0;
goto iostart;
case 28: /* Rewind */
opcode = IO_REW;
iostart:
switch (chan_cmd(MA, opcode)) {
case SCPE_BUSY:
iowait = 1; /* Channel is active, hold */
case SCPE_OK:
ihold = 1; /* Hold interupts for one */
break;
case SCPE_IOERR:
iocheck = 1;
break;
case SCPE_NODEV:
reason = STOP_IOCHECK;
break;
}
break;
default:
reason = STOP_UUO;
break;
}
chan_proc(); /* process any pending channel events */
if (instr_count != 0 && --instr_count == 0)
return SCPE_STEP;
} /* end while */
/* Simulation halted */
return reason;
}
/* Reset routine */
t_stat
cpu_reset(DEVICE * dptr)
{
AC = 0;
MQ = 0;
dualcore = 0;
iotraps = 0;
ioflags = 0;
dcheck = acoflag = iocheck = 0;
sim_brk_types = sim_brk_dflt = SWMASK('E');
return SCPE_OK;
}
/* Memory examine */
t_stat
cpu_ex(t_value * vptr, t_addr addr, UNIT * uptr, int32 sw)
{
if (addr >= (MEMSIZE * 2))
return SCPE_NXM;
if (vptr == NULL)
return SCPE_OK;
*vptr = M[(addr & 07777) >> 1];
if ((addr & 0400000) == 0) {
if ( addr & 1)
*vptr <<= 18;
else
*vptr &= LMASK;
}
*vptr &= 0777777777777L;
return SCPE_OK;
}
/* Memory deposit */
t_stat
cpu_dep(t_value val, t_addr addr, UNIT * uptr, int32 sw)
{
t_addr a = (addr >> 1) & 03777;
if (addr >= (MEMSIZE * 2))
return SCPE_NXM;
if ((addr & 0400000) == 0) {
if (addr & 1) {
M[a] &= LMASK;
M[a] |= (val >> 18) & RMASK;
} else {
M[a] &= RMASK;
M[a] |= val & LMASK;
}
} else
M[a] = val & 0777777777777L;
return SCPE_OK;
}
/* Handle execute history */
/* Set history */
t_stat
cpu_set_hist(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
{
int32 i, lnt;
t_stat r;
if (cptr == NULL) {
for (i = 0; i < hst_lnt; i++)
hst[i].ic = 0;
hst_p = 0;
return SCPE_OK;
}
lnt = (int32) get_uint(cptr, 10, HIST_MAX, &r);
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
return SCPE_ARG;
hst_p = 0;
if (hst_lnt) {
free(hst);
hst_lnt = 0;
hst = NULL;
}
if (lnt) {
hst = (struct InstHistory *)calloc(sizeof(struct InstHistory), lnt);
if (hst == NULL)
return SCPE_MEM;
hst_lnt = lnt;
}
return SCPE_OK;
}
/* Show history */
t_stat
cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc)
{
int32 k, di, lnt;
char *cptr = (char *) desc;
t_stat r;
t_value sim_eval;
struct InstHistory *h;
if (hst_lnt == 0)
return SCPE_NOFNC; /* enabled? */
if (cptr) {
lnt = (int32) get_uint(cptr, 10, hst_lnt, &r);
if ((r != SCPE_OK) || (lnt == 0))
return SCPE_ARG;
} else
lnt = hst_lnt;
di = hst_p - lnt; /* work forward */
if (di < 0)
di = di + hst_lnt;
fprintf(st, "IC AC MQ EA SR\n\n");
for (k = 0; k < lnt; k++) { /* print specified */
h = &hst[(++di) % hst_lnt]; /* entry pointer */
if (h->ic & HIST_PC) { /* instruction? */
fprintf(st, "%06lo ", h->ic & AMASK);
switch (h->ac & (AMSIGN | AQSIGN | APSIGN)) {
case AMSIGN | AQSIGN | APSIGN:
fprintf(st, "-QP");
break;
case AMSIGN | AQSIGN:
fprintf(st, " -Q");
break;
case AMSIGN | APSIGN:
fprintf(st, " -P");
break;
case AMSIGN:
fprintf(st, " -");
break;
case AQSIGN | APSIGN:
fprintf(st, " QP");
break;
case AQSIGN:
fprintf(st, " Q");
break;
case APSIGN:
fprintf(st, " P");
break;
case 0:
fprintf(st, " ");
break;
}
fprint_val(st, h->ac & PMASK, 8, 35, PV_RZRO);
fputc(' ', st);
if (h->mq & MSIGN)
fputc('-', st);
else
fputc(' ', st);
fprint_val(st, h->mq & PMASK, 8, 35, PV_RZRO);
fputc(' ', st);
fprint_val(st, h->ea, 8, 12, PV_RZRO);
fputc(' ', st);
if (h->sr & MSIGN)
fputc('-', st);
else
fputc(' ', st);
fprint_val(st, h->sr & PMASK, 8, 35, PV_RZRO);
fputc(' ', st);
sim_eval = h->op;
if (
(fprint_sym
(st, h->ic & AMASK, &sim_eval, &cpu_unit,
SWMASK('M'))) > 0) fprintf(st, "(undefined) %012llo",
h->op);
fputc('\n', st); /* end line */
} /* end else instruction */
} /* end for */
return SCPE_OK;
}
const char *
cpu_description (DEVICE *dptr)
{
return "IBM 701 CPU";
}
t_stat
cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
fprintf (st, "The CPU behaves as a IBM 701\n");
fprintf (st, "These switches are recognized when examining or depositing in CPU memory:\n\n");
fprintf (st, " -c examine/deposit characters, 6 per word\n");
fprintf (st, " -l examine/deposit half words\n");
fprintf (st, " -m examine/deposit IBM 701 instructions\n\n");
fprintf (st, "The CPU can maintain a history of the most recently executed instructions.\n");
fprintf (st, "This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:\n\n");
fprintf (st, " sim> SET CPU HISTORY clear history buffer\n");
fprintf (st, " sim> SET CPU HISTORY=0 disable history\n");
fprintf (st, " sim> SET CPU HISTORY=n{:file} enable history, length = n\n");
fprintf (st, " sim> SHOW CPU HISTORY print CPU history\n");
fprint_set_help(st, dptr);
fprint_show_help(st, dptr);
return SCPE_OK;
}