These include simulators for the IBM 701, IBM 702, IBM 704, IBM 705, IBM 705/3, IBM 709, IBM 1410/IBM 7010, IBM 7070, IBM 7080, IBM 7090 and IBM7094. These basically were a collection of machines that shared a common set it peripherals, Each group had its own instruction set, hence different simulators. IBM 701 -> i701 IBM 702/705/705/3/7080 -> i7080 IBM 7070/7074 -> i7070 IBM 1410/7010 -> i7010 IBM 704 -> i704 IBM 704/709/7090/7094 -> i7090 The i7090 can be set to simulate a IBM 704 however you end up disabling almost everything, since the 704 did not have any channels. A build option exists that allows this one to be built without all the extra features. The i7090 simulator’s implementation of the IBM 7094 is a more complete implementation of the IBM 7094 which can run CTSS while the existing simh I7094 can’t.
729 lines
22 KiB
C
729 lines
22 KiB
C
/* i7090_sys.c: IBM 705 Simulator system interface.
|
||
|
||
Copyright (c) 2006-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.
|
||
|
||
*/
|
||
|
||
#include "i7080_defs.h"
|
||
#include "sim_card.h"
|
||
#include <ctype.h>
|
||
|
||
/* SCP data structures and interface routines
|
||
|
||
sim_name simulator name string
|
||
sim_PC pointer to saved PC register descriptor
|
||
sim_emax number of words for examine
|
||
sim_devices array of pointers to simulated devices
|
||
sim_stop_messages array of pointers to stop messages
|
||
sim_load binary loader
|
||
*/
|
||
|
||
char sim_name[] = "IBM 7080";
|
||
|
||
REG *sim_PC = &cpu_reg[0];
|
||
|
||
int32 sim_emax = 50;
|
||
|
||
#ifdef NUM_DEVS_CDP
|
||
extern DEVICE stack_dev[];
|
||
#endif
|
||
|
||
DEVICE *sim_devices[] = {
|
||
&cpu_dev,
|
||
&chan_dev,
|
||
#if NUM_DEVS_CDR > 0
|
||
&cdr_dev,
|
||
#endif
|
||
#if NUM_DEVS_CDP > 0
|
||
&cdp_dev,
|
||
#endif
|
||
#ifdef STACK_DEV
|
||
&stack_dev,
|
||
#endif
|
||
#if NUM_DEVS_LPR > 0
|
||
&lpr_dev,
|
||
#endif
|
||
#if NUM_DEVS_CON > 0
|
||
&con_dev,
|
||
#endif
|
||
#if NUM_DEVS_MT > 0
|
||
&mta_dev,
|
||
#if NUM_DEVS_MT > 1
|
||
&mtb_dev,
|
||
#if NUM_DEVS_MT > 2
|
||
&mtc_dev,
|
||
#if NUM_DEVS_MT > 3
|
||
&mtd_dev,
|
||
#endif
|
||
#endif
|
||
#endif
|
||
#endif
|
||
#if NUM_DEVS_DR > 0
|
||
&drm_dev,
|
||
#endif
|
||
#if NUM_DEVS_HT > 0
|
||
&hta_dev,
|
||
#if NUM_DEVS_HT > 1
|
||
&htb_dev,
|
||
#endif
|
||
#endif
|
||
#if NUM_DEVS_DSK > 0
|
||
&dsk_dev,
|
||
#endif
|
||
#if NUM_DEVS_COM > 0
|
||
&coml_dev,
|
||
&com_dev,
|
||
#endif
|
||
#if NUM_DEVS_CHRON > 0
|
||
&chron_dev,
|
||
#endif
|
||
NULL
|
||
};
|
||
|
||
/* Device addressing words */
|
||
#ifdef NUM_DEVS_CDP
|
||
DIB cdp_dib = { CH_TYP_UREC, 1, 0x300, 0xff00, &cdp_cmd, &cdp_ini };
|
||
#endif
|
||
#ifdef NUM_DEVS_CDR
|
||
DIB cdr_dib = { CH_TYP_UREC, 1, 0x100, 0xff00, &cdr_cmd, NULL };
|
||
#endif
|
||
#ifdef NUM_DEVS_LPR
|
||
DIB lpr_dib = { CH_TYP_UREC, 1, 0x400, 0xff00, &lpr_cmd, &lpr_ini };
|
||
#endif
|
||
#ifdef NUM_DEVS_CON
|
||
DIB con_dib = { CH_TYP_UREC, 1, 0x500, 0xff00, &con_cmd, &con_ini };
|
||
#endif
|
||
#ifdef NUM_DEVS_DR
|
||
DIB drm_dib = { CH_TYP_UREC, 1, 0x1000, 0xff00, &drm_cmd, &drm_ini };
|
||
#endif
|
||
#ifdef NUM_DEVS_MT
|
||
DIB mt_dib = { CH_TYP_76XX|CH_TYP_754, NUM_UNITS_MT, 0x200, 0xff00, &mt_cmd, &mt_ini };
|
||
#endif
|
||
#ifdef NUM_DEVS_CHRON
|
||
DIB chron_dib = { CH_TYP_76XX|CH_TYP_UREC, 1, 0x200, 0xff00, &chron_cmd, NULL };
|
||
#endif
|
||
#ifdef NUM_DEVS_HT
|
||
DIB ht_dib = { CH_TYP_79XX, NUM_UNITS_HT, 0, 0, &ht_cmd, NULL };
|
||
#endif
|
||
#ifdef NUM_DEVS_DSK
|
||
DIB dsk_dib = { CH_TYP_79XX, 0, 0, 0, &dsk_cmd, &dsk_ini };
|
||
#endif
|
||
#ifdef NUM_DEVS_COM
|
||
DIB com_dib = { CH_TYP_79XX, 0, 0, 0, &com_cmd, NULL };
|
||
#endif
|
||
|
||
/* Simulator stop codes */
|
||
const char *sim_stop_messages[] = {
|
||
"Unknown error",
|
||
"IO device not ready",
|
||
"HALT instruction",
|
||
"Breakpoint",
|
||
"Unknown Opcode",
|
||
"Error1", /* Ind limit */ /* Not on 7080 */
|
||
"Error2", /* XEC limit */ /* Not on 7080 */
|
||
"I/O Check opcode",
|
||
"Machine Check", /* MM in trap */
|
||
"7750 invalid line number",
|
||
"7750 invalid message",
|
||
"7750 No free output buffers",
|
||
"7750 No free input buffers",
|
||
"Overflow Check", /* Field overflow */
|
||
"Sign Check", /* Sign change */
|
||
"Divide error",
|
||
"Error6", /* Alpha index */ /* Not on 7080 */
|
||
"No word mark",
|
||
"Invalid Address",
|
||
"Record Check",
|
||
"Program Check",
|
||
"Protect Check",
|
||
0,
|
||
};
|
||
|
||
|
||
/* Simulator debug controls */
|
||
DEBTAB dev_debug[] = {
|
||
{"CHANNEL", DEBUG_CHAN},
|
||
{"TRAP", DEBUG_TRAP},
|
||
{"CMD", DEBUG_CMD},
|
||
{"DATA", DEBUG_DATA},
|
||
{"DETAIL", DEBUG_DETAIL},
|
||
{"EXP", DEBUG_EXP},
|
||
{"SENSE", DEBUG_SNS},
|
||
{0, 0}
|
||
};
|
||
|
||
DEBTAB crd_debug[] = {
|
||
{"CHAN", DEBUG_CHAN},
|
||
{"CMD", DEBUG_CMD},
|
||
{"DATA", DEBUG_DATA},
|
||
{"DETAIL", DEBUG_DETAIL},
|
||
{"EXP", DEBUG_EXP},
|
||
{"CARD", DEBUG_CARD},
|
||
{0, 0}
|
||
};
|
||
|
||
|
||
const char mem_to_ascii[64] = {
|
||
'a', '1', '2', '3', '4', '5', '6', '7',
|
||
'8', '9', '0', '=', '\'', ':', '>', 's',
|
||
' ', '/', 'S', 'T', 'U', 'V', 'W', 'X',
|
||
'Y', 'Z', '#', ',', '(', '`', '\\', '_',
|
||
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||
'Q', 'R', '!', '$', '*', ']', ';', '^',
|
||
'+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||
'H', 'I', '?', '.', ')', '[', '<', '|',
|
||
/*Sq*/ /*GM*/
|
||
};
|
||
|
||
t_stat parse_sym(CONST char *, t_addr, UNIT *, t_value *, int32);
|
||
|
||
|
||
|
||
/* Load BCD card image into memory, following 705 standard load format */
|
||
int
|
||
load_rec(uint8 *image) {
|
||
extern uint8 bcd_bin[16];
|
||
extern uint32 IC;
|
||
uint32 addr;
|
||
int len, i;
|
||
|
||
/* Convert blanks to space code */
|
||
for(i = 0; i < 80; i++)
|
||
if (image[i] == 0)
|
||
image[i] = 020;
|
||
|
||
addr = bcd_bin[image[12] & 0xf];
|
||
addr += 10 * bcd_bin[image[11] & 0xf];
|
||
addr += 100 * bcd_bin[image[10] & 0xf];
|
||
addr += 1000 * bcd_bin[image[9] & 0xf];
|
||
i = (image[9] & 060) >> 4; /* Handle zones */
|
||
i |= (image[12] & 040) >> 3;
|
||
i |= (image[12] & 020) >> 1;
|
||
addr += 10000 * i;
|
||
while(addr > EMEMSIZE) addr -= EMEMSIZE; /* Wrap around */
|
||
len = bcd_bin[image[14] & 0xf];
|
||
len += 10 * bcd_bin[image[13] & 0xf];
|
||
if (len > 65)
|
||
len = 65;
|
||
if (len == 0) {
|
||
IC = addr;
|
||
return 1;
|
||
}
|
||
for(i = 0; i < len; i++) {
|
||
uint8 ch = image[15+i];
|
||
if (ch == 075)
|
||
ch = 077;
|
||
M[addr++] = ch;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/* Load a card image file into memory. */
|
||
t_stat
|
||
sim_load(FILE * fileref, CONST char *cptr, CONST char *fnam, int flag)
|
||
{
|
||
char buffer[160];
|
||
int i, j;
|
||
|
||
if (match_ext(fnam, "crd")) {
|
||
uint8 image[80];
|
||
|
||
while (sim_fread(buffer, 1, 160, fileref) == 160) {
|
||
/* Convert bits into image */
|
||
for (j = i = 0; j < 80; j++) {
|
||
uint16 x;
|
||
x = buffer[i++];
|
||
x |= buffer[i++] << 8;
|
||
image[j] = sim_hol_to_bcd(x);
|
||
}
|
||
if (load_rec(image))
|
||
return SCPE_OK;
|
||
}
|
||
return SCPE_OK;
|
||
} else if (match_ext(fnam, "cbn")) {
|
||
uint8 image[80];
|
||
|
||
while (sim_fread(buffer, 1, 160, fileref) == 160) {
|
||
/* Convert bits into image */
|
||
for (j = i = 0; j < 80; j++) {
|
||
uint16 x;
|
||
x = buffer[i++];
|
||
x |= buffer[i++] << 8;
|
||
image[j] = sim_hol_to_bcd(x);
|
||
}
|
||
if (load_rec(image))
|
||
return SCPE_OK;
|
||
}
|
||
return SCPE_OK;
|
||
} else if (match_ext(fnam, "dck")) {
|
||
extern char ascii_to_six[128];
|
||
while (fgets(buffer, 160, fileref) != 0) {
|
||
uint8 image[80];
|
||
/* Convert bits into image */
|
||
memset(image, 0, sizeof(image));
|
||
for (j = 0; j < 80; j++) {
|
||
if (buffer[j] == '\n' || buffer[j] == '\0')
|
||
break;
|
||
image[j] = sim_ascii_to_six[buffer[j]&0177];
|
||
}
|
||
if (load_rec(image))
|
||
return SCPE_OK;
|
||
}
|
||
return SCPE_OK;
|
||
} else
|
||
return SCPE_ARG;
|
||
|
||
|
||
|
||
return SCPE_ARG;
|
||
}
|
||
|
||
/* Symbol tables */
|
||
typedef struct _opcode
|
||
{
|
||
uint32 opbase;
|
||
const char *name;
|
||
uint8 type;
|
||
}
|
||
t_opcode;
|
||
|
||
const char *chname[11] = {
|
||
"*", "20", "21", "22", "23", "40", "41", "44", "45", "46", "47"
|
||
};
|
||
|
||
#define TYPE_A 1 /* Standard memory operation */
|
||
#define TYPE_B 2 /* ASU encoded operation */
|
||
#define TYPE_C 3 /* MA encoded operation MA < 100 */
|
||
#define TYPE_D 4 /* MA + ASU fixed MA < 100 */
|
||
|
||
t_opcode optbl[] = {
|
||
{OP_ADD, "ADD", TYPE_A},
|
||
{OP_RAD, "RAD", TYPE_A},
|
||
{OP_SUB, "SUB", TYPE_A},
|
||
{OP_RSU, "RSU", TYPE_A},
|
||
{OP_MPY, "MPY", TYPE_A},
|
||
{OP_DIV, "DIV", TYPE_A},
|
||
{OP_ST, "ST", TYPE_A},
|
||
{OP_ADM, "ADM", TYPE_A},
|
||
{OP_AAM, "AAM", TYPE_A},
|
||
{OP_SGN, "SGN", TYPE_A},
|
||
{OP_SET, "SET", TYPE_A},
|
||
{OP_SHR, "SHR", TYPE_A},
|
||
{OP_LEN, "LNG", TYPE_A},
|
||
{OP_RND, "RND", TYPE_A},
|
||
{OP_LOD, "LOD", TYPE_A},
|
||
{OP_UNL, "UNL", TYPE_A},
|
||
{OP_LDA, "LDA", TYPE_A},
|
||
{OP_ULA, "ULA", TYPE_A},
|
||
{OP_SPR, "SPR", TYPE_A},
|
||
{OP_RCV, "RCV", TYPE_A},
|
||
{OP_SND, "SND", TYPE_A},
|
||
{OP_CMP, "CMP", TYPE_A},
|
||
{OP_TRE, "TRE", TYPE_A},
|
||
{OP_TRH, "TRH", TYPE_A},
|
||
{OP_NTR, "NTR", TYPE_A},
|
||
{OP_TRP, "TRP", TYPE_A},
|
||
{OP_TRZ, "TRZ", TYPE_A},
|
||
{OP_NOP, "NOP", TYPE_A},
|
||
{OP_TR|000100, "TSL", TYPE_B},
|
||
{OP_TR, "TR", TYPE_A},
|
||
{OP_TRA|000100, "TAA", TYPE_B},
|
||
{OP_TRA|000200, "TAB", TYPE_B},
|
||
{OP_TRA|000300, "TAC", TYPE_B},
|
||
{OP_TRA|000400, "TAD", TYPE_B},
|
||
{OP_TRA|000500, "TAE", TYPE_B},
|
||
{OP_TRA|000600, "TAF", TYPE_B},
|
||
{OP_TRA|000700, "TNS", TYPE_B},
|
||
{OP_TRA, "TRA", TYPE_A},
|
||
{OP_TRS|000100, "TRR", TYPE_B},
|
||
{OP_TRS|000200, "TTC", TYPE_B},
|
||
{OP_TRS|000300, "TSA", TYPE_B},
|
||
{OP_TRS|001100, "TAR", TYPE_B},
|
||
{OP_TRS|001200, "TIC", TYPE_B},
|
||
{OP_TRS|001300, "TMC", TYPE_B},
|
||
{OP_TRS|001400, "TRC", TYPE_B},
|
||
{OP_TRS|001500, "TEC", TYPE_B},
|
||
{OP_TRS|001600, "TOC", TYPE_B},
|
||
{OP_TRS|001700, "TSC", TYPE_B},
|
||
{OP_TRS, "TRS", TYPE_A},
|
||
{OP_TMT, "TMT", TYPE_A},
|
||
{OP_CTL2|000000,"SPC", TYPE_B},
|
||
{OP_CTL2|000200,"LFC", TYPE_B},
|
||
{OP_CTL2|000300,"UFC", TYPE_B},
|
||
{OP_CTL2|000400,"LSB", TYPE_B},
|
||
{OP_CTL2|000500,"USB", TYPE_B},
|
||
{OP_CTL2|000600,"EIM", TYPE_B},
|
||
{OP_CTL2|000700,"LIM", TYPE_B},
|
||
{OP_CTL2|001000,"TCT", TYPE_B},
|
||
{OP_CTL2|001100,"B", TYPE_B},
|
||
{OP_CTL2|001200,"EIA", TYPE_B},
|
||
{OP_CTL2|001300,"CNO", TYPE_B},
|
||
{OP_CTL2|001400,"TLU", TYPE_B},
|
||
{OP_CTL2|001500,"TLH", TYPE_B},
|
||
{OP_CTL2|001600,"TIP", TYPE_B},
|
||
{OP_CTL2|001700,"LIP", TYPE_B},
|
||
{OP_CTL2, "CTL2", TYPE_A},
|
||
{OP_BLM|000100, "BLMS", TYPE_B},
|
||
{OP_BLM, "BLM", TYPE_A},
|
||
{OP_SEL, "SEL", TYPE_A},
|
||
{OP_CTL|001400, "ECB", TYPE_B},
|
||
{OP_CTL|001500, "CHR", TYPE_B},
|
||
{OP_CTL|001600, "EEM", TYPE_B},
|
||
{OP_CTL|001700, "LEM", TYPE_B},
|
||
{OP_CTL|0010000, "WTM", TYPE_D},
|
||
{OP_CTL|0020100, "RUN", TYPE_D},
|
||
{OP_CTL|0020000, "RWD", TYPE_D},
|
||
{OP_CTL|0030000, "ION", TYPE_D},
|
||
{OP_CTL|0040100, "BSF", TYPE_D},
|
||
{OP_CTL|0040000, "BSP", TYPE_D},
|
||
{OP_CTL|0050000, "SUP", TYPE_C},
|
||
{OP_CTL|0110000, "SKP", TYPE_C},
|
||
{OP_CTL|0450000, "SDL", TYPE_C},
|
||
{OP_CTL|0460000, "SDH", TYPE_C},
|
||
{OP_CTL|0000000, "IOF", TYPE_D},
|
||
{OP_CTL, "CTL", TYPE_A},
|
||
{OP_HLT, "HLT", TYPE_A},
|
||
{OP_WR|000500, "WMC", TYPE_B},
|
||
{OP_WR|000400, "CWR", TYPE_B},
|
||
{OP_WR|000300, "SCC", TYPE_B},
|
||
{OP_WR|000200, "SRC", TYPE_B},
|
||
{OP_WR|000100, "DMP", TYPE_B},
|
||
{OP_WR, "WR", TYPE_A},
|
||
{OP_RWW, "RWW", TYPE_A},
|
||
{OP_RD|000500, "RMB", TYPE_B},
|
||
{OP_RD|000400, "CRD", TYPE_B},
|
||
{OP_RD|000300, "SST", TYPE_B},
|
||
{OP_RD|000200, "RMA", TYPE_B},
|
||
{OP_RD|000100, "FSP", TYPE_B},
|
||
{OP_RD, "RD", TYPE_A},
|
||
{OP_WRE|000100, "WRZ", TYPE_B},
|
||
{OP_WRE, "WRE", TYPE_A},
|
||
{OP_SBZ|000100, "SBZ1", TYPE_B},
|
||
{OP_SBZ|000200, "SBZ2", TYPE_B},
|
||
{OP_SBZ|000300, "SBZ3", TYPE_B},
|
||
{OP_SBZ|000400, "SBZ4", TYPE_B},
|
||
{OP_SBZ|000500, "SBZ5", TYPE_B},
|
||
{OP_SBZ|000600, "SBZ6", TYPE_B},
|
||
{OP_SBZ|000700, "SBA", TYPE_B},
|
||
{OP_SBZ|001000, "SBR", TYPE_B},
|
||
{OP_SBZ|001100, "SBN1", TYPE_B},
|
||
{OP_SBZ|001200, "SBN2", TYPE_B},
|
||
{OP_SBZ|001300, "SBN3", TYPE_B},
|
||
{OP_SBZ|001400, "SBN4", TYPE_B},
|
||
{OP_SBZ|001500, "SBN5", TYPE_B},
|
||
{OP_SBZ|001600, "SBN6", TYPE_B},
|
||
{OP_SBZ, "SBZ", TYPE_A},
|
||
{OP_TZB, "TZB", TYPE_A},
|
||
{OP_SMT|001600, "SMT", TYPE_A},
|
||
{0, NULL, 0},
|
||
};
|
||
|
||
|
||
/* Print out a address plus index */
|
||
t_stat fprint_addr (FILE *of, uint32 addr) {
|
||
fprintf(of, "%d", addr);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Register change decode
|
||
|
||
Inputs:
|
||
*of = output stream
|
||
inst = mask bits
|
||
*/
|
||
|
||
t_stat
|
||
fprint_reg (FILE *of, uint32 rdx, t_value *val, UNIT *uptr, int32 sw)
|
||
{
|
||
fprintf(of, "Register(%d, %x)", rdx, *val);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
|
||
|
||
/* Symbolic decode
|
||
|
||
Inputs:
|
||
*of = output stream
|
||
addr = current PC
|
||
*val = pointer to values
|
||
*uptr = pointer to unit
|
||
sw = switches
|
||
Outputs:
|
||
return = status code
|
||
*/
|
||
|
||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
||
{
|
||
int32 i, t;
|
||
uint8 op;
|
||
|
||
if (sw & SIM_SW_REG)
|
||
return fprint_reg(of, addr, val, uptr, sw);
|
||
|
||
if (sw & SWMASK ('C')) { /* character? */
|
||
t = val[0];
|
||
fprintf (of, " %c<%02o> ", mem_to_ascii[t & 077], t & 077);
|
||
return SCPE_OK;
|
||
}
|
||
if ((uptr != NULL) && (uptr != &cpu_unit)) return SCPE_ARG; /* CPU? */
|
||
if (sw & SWMASK ('D')) { /* dump? */
|
||
for (i = 0; i < 50; i++) fprintf (of, "%c", mem_to_ascii[val[i]&077]) ;
|
||
return -(i - 1);
|
||
}
|
||
if (sw & SWMASK ('S')) { /* string? */
|
||
i = 0;
|
||
do {
|
||
t = val[i++];
|
||
fprintf (of, "%c", mem_to_ascii[t & 077]);
|
||
} while (i < 50);
|
||
return -(i - 1);
|
||
}
|
||
if (sw & SWMASK ('M')) { /* machine code? */
|
||
uint32 addr;
|
||
t_opcode *tab;
|
||
uint8 zone;
|
||
uint8 reg;
|
||
uint16 opvalue;
|
||
|
||
i = 0;
|
||
op = val[i++] & 077;
|
||
t = val[i++]; /* First address char */
|
||
zone = (t & 060) >> 4;
|
||
t &= 0xf;
|
||
if (t == 10)
|
||
t = 0;
|
||
addr = t * 1000;
|
||
t = val[i++]; /* Second address char */
|
||
reg = (t & 060) >> 2;
|
||
t &= 0xf;
|
||
if (t == 10)
|
||
t = 0;
|
||
addr += t * 100;
|
||
t = val[i++]; /* Third address char */
|
||
reg |= (t & 060) >> 4;
|
||
t &= 0xf;
|
||
if (t == 10)
|
||
t = 0;
|
||
addr += t * 10;
|
||
t = val[i++]; /* Forth address char */
|
||
zone |= (t & 060) >> 2;
|
||
/* Switch BA bits in high zone */
|
||
zone = (zone & 03) | ((zone & 04) << 1) | ((zone & 010) >> 1);
|
||
t &= 0xf;
|
||
if (t == 10)
|
||
t = 0;
|
||
addr += t;
|
||
opvalue = op | (reg << 6);
|
||
addr += zone * 10000;
|
||
for(tab = optbl; tab->name != NULL; tab++) {
|
||
if (tab->type == TYPE_A && op == tab->opbase)
|
||
break;
|
||
if (tab->type == TYPE_B && opvalue == tab->opbase)
|
||
break;
|
||
if (tab->type == TYPE_C && addr < 100 &&
|
||
(op|(addr << 12)) == tab->opbase)
|
||
break;
|
||
if (tab->type == TYPE_D && addr < 100 &&
|
||
(opvalue|(addr << 12)) == tab->opbase)
|
||
break;
|
||
}
|
||
|
||
if (tab->name == NULL)
|
||
fprintf(of, "%c<%02o>\t", mem_to_ascii[op], op);
|
||
else
|
||
fprintf(of, "%s\t", tab->name);
|
||
|
||
switch(tab->type) {
|
||
case TYPE_A:
|
||
fprintf(of, "%d", addr);
|
||
if (reg != 0)
|
||
fprintf(of, ",%d", reg);
|
||
break;
|
||
case TYPE_B:
|
||
fprintf(of, "%d", addr);
|
||
break;
|
||
case TYPE_C: /* No operand required for type C or D */
|
||
case TYPE_D:
|
||
break;
|
||
}
|
||
return -(i - 1);
|
||
}
|
||
fprintf (of, " %02o ", val[0] & 077);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_opcode *
|
||
find_opcode(char *op, t_opcode * tab)
|
||
{
|
||
while (tab->name != NULL) {
|
||
if (*tab->name != '\0' && strcmp(op, tab->name) == 0)
|
||
return tab;
|
||
tab++;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/* Symbolic input
|
||
|
||
Inputs:
|
||
*cptr = pointer to input string
|
||
addr = current PC
|
||
uptr = pointer to unit
|
||
*val = pointer to output values
|
||
sw = switches
|
||
Outputs:
|
||
status = error status
|
||
*/
|
||
|
||
t_stat
|
||
parse_sym(CONST char *cptr, t_addr addr, UNIT * uptr, t_value * val, int32 sw)
|
||
{
|
||
int i;
|
||
t_value d;
|
||
char buffer[100];
|
||
extern char ascii_to_six[];
|
||
|
||
while (isspace(*cptr))
|
||
cptr++;
|
||
d = 0;
|
||
i = 0;
|
||
if (sw & SWMASK('C')) {
|
||
while (*cptr != '\0') {
|
||
d = sim_ascii_to_six[0177 & *cptr++];
|
||
if (d == 0)
|
||
d = 020;
|
||
val[i++] = d;
|
||
}
|
||
if (i == 0)
|
||
return SCPE_ARG;
|
||
return -(i - 1);
|
||
} else if (sw & SWMASK('M')) {
|
||
t_opcode *op;
|
||
uint32 addr = 0;
|
||
uint8 asu = 0;
|
||
uint8 zone;
|
||
uint8 t;
|
||
|
||
i = 0;
|
||
/* Grab opcode */
|
||
cptr = get_glyph(cptr, buffer, 0);
|
||
if ((op = find_opcode(buffer, optbl)) == 0)
|
||
return STOP_UUO;
|
||
if (op->type == TYPE_C || op->type == TYPE_D) {
|
||
addr = op->opbase >> 12;
|
||
val[i++] = op->opbase & 077;
|
||
val[i++] = 10;
|
||
val[i++] = ((op->opbase & 01400) >> 4) | 10;
|
||
t = addr / 10;
|
||
if (t == 0)
|
||
t = 10;
|
||
val[i++] = ((op->opbase & 00300) >> 2) | t;
|
||
t = addr % 10;
|
||
if (t == 0)
|
||
t = 10;
|
||
val[i++] = t;
|
||
return -(i - 1);
|
||
}
|
||
/* Skip blanks */
|
||
while(isspace(*cptr)) cptr++;
|
||
/* Collect address */
|
||
while(*cptr >= '0' && *cptr <= '9')
|
||
addr = (addr * 10) + (*cptr++ - '0');
|
||
/* Skip blanks */
|
||
while(isspace(*cptr)) cptr++;
|
||
if (*cptr == ',') { /* Collect a ASU */
|
||
while(*cptr >= '0' && *cptr <= '9')
|
||
asu = (asu * 10) + (*cptr++ - '0');
|
||
|
||
}
|
||
/* Skip blanks */
|
||
while(isspace(*cptr)) cptr++;
|
||
if (*cptr != '\0')
|
||
return SCPE_ARG;
|
||
/* Type B's can't have ASU */
|
||
if (op->type == TYPE_B) {
|
||
if (asu != 0)
|
||
return STOP_UUO;
|
||
asu = (op->opbase >> 6) & 017;
|
||
}
|
||
/* Check if ASU out of range */
|
||
if (asu > 16)
|
||
return SCPE_ARG;
|
||
zone = addr / 10000;
|
||
if (zone > 16)
|
||
return SCPE_ARG;
|
||
addr %= 10000;
|
||
val[i++] = op->opbase & 077;
|
||
t = addr / 1000;
|
||
if (t == 0)
|
||
t = 10;
|
||
addr %= 1000;
|
||
val[i++] = t | ((zone << 4) & 060);
|
||
t = addr / 100;
|
||
if (t == 0)
|
||
t = 10;
|
||
addr %= 100;
|
||
val[i++] = t | ((asu << 2) & 060);
|
||
t = addr / 10;
|
||
if (t == 0)
|
||
t = 10;
|
||
addr %= 10;
|
||
val[i++] = t | ((asu << 4) & 060);
|
||
t = addr;
|
||
if (t == 0)
|
||
t = 10;
|
||
addr %= 10;
|
||
val[i++] = t | ((zone << 2) & 060);
|
||
return -(i - 1);
|
||
} else {
|
||
int sign = 0;
|
||
|
||
i = 0;
|
||
while (*cptr != '\0') {
|
||
sign = 0;
|
||
/* Skip blanks */
|
||
while(isspace(*cptr)) cptr++;
|
||
if (*cptr == '+') {
|
||
cptr++;
|
||
sign = 1;
|
||
} else if (*cptr == '-') {
|
||
cptr++;
|
||
sign = -1;
|
||
}
|
||
if (!(*cptr >= '0' && *cptr <= '9'))
|
||
return SCPE_ARG;
|
||
while(*cptr >= '0' && *cptr <= '9') {
|
||
d = *cptr++ - '0';
|
||
if (d == 0)
|
||
d = 10;
|
||
val[i++] = d;
|
||
}
|
||
if (*cptr == ',')
|
||
cptr++;
|
||
if(sign)
|
||
val[i-1] |= (sign==-1)?040:060; /* Set sign last digit */
|
||
}
|
||
if (i == 0)
|
||
return SCPE_ARG;
|
||
return -(i - 1);
|
||
}
|
||
return SCPE_OK;
|
||
}
|