317 lines
10 KiB
C
317 lines
10 KiB
C
/* id4_sys.c: Interdata 4 simulator interface
|
||
|
||
Copyright (c) 1993-2000, Robert M. Supnik
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a
|
||
copy of this software and associated documentation files (the "Software"),
|
||
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
|
||
ROBERT M SUPNIK 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.
|
||
|
||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||
in this Software without prior written authorization from Robert M Supnik.
|
||
|
||
30-Oct-00 RMS Added support for examine to file
|
||
27-Oct-98 RMS V2.4 load interface
|
||
*/
|
||
|
||
#include "id4_defs.h"
|
||
#include <ctype.h>
|
||
|
||
extern DEVICE cpu_dev;
|
||
extern DEVICE pt_dev, tt_dev;
|
||
extern UNIT cpu_unit;
|
||
extern REG cpu_reg[];
|
||
extern unsigned int16 *M;
|
||
extern int32 saved_PC;
|
||
|
||
/* 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[] = "Interdata 4";
|
||
|
||
REG *sim_PC = &cpu_reg[0];
|
||
|
||
int32 sim_emax = 2;
|
||
|
||
DEVICE *sim_devices[] = { &cpu_dev,
|
||
&pt_dev, &tt_dev,
|
||
NULL };
|
||
|
||
const char *sim_stop_messages[] = {
|
||
"Unknown error",
|
||
"Reserved instruction",
|
||
"HALT instruction",
|
||
"Breakpoint",
|
||
"Wait state" };
|
||
|
||
/* Binary loader.
|
||
|
||
To be specified
|
||
*/
|
||
|
||
t_stat sim_load (FILE *fileref, char *cptr, int flag)
|
||
{
|
||
return SCPE_FMT; /* unexpected eof */
|
||
}
|
||
|
||
/* Symbol tables */
|
||
|
||
#define I_V_FL 16 /* class bits */
|
||
#define I_M_FL 07 /* class mask */
|
||
#define I_V_MR 0 /* mask-register */
|
||
#define I_V_RR 1 /* register-register */
|
||
#define I_V_R 2 /* register */
|
||
#define I_V_MX 3 /* mask-memory */
|
||
#define I_V_RX 4 /* register-memory */
|
||
#define I_V_X 5 /* memory */
|
||
#define I_V_FF 6 /* float reg-reg */
|
||
#define I_V_FX 7 /* float reg-mem */
|
||
#define I_MR (I_V_MR << I_V_FL)
|
||
#define I_RR (I_V_RR << I_V_FL)
|
||
#define I_R (I_V_R << I_V_FL)
|
||
#define I_MX (I_V_MX << I_V_FL)
|
||
#define I_RX (I_V_RX << I_V_FL)
|
||
#define I_X (I_V_X << I_V_FL)
|
||
#define I_FF (I_V_FF << I_V_FL)
|
||
#define I_FX (I_V_FX << I_V_FL)
|
||
|
||
static const int32 masks[] =
|
||
{ 0xFFF0, 0xFF00, 0xFFF0, 0xFF00,
|
||
0xFF00, 0xFFF0, 0xFF00, 0xFF00 };
|
||
|
||
static const char *opcode[] = {
|
||
"BZ", "BNZ", "BE", "BNE",
|
||
"BP", "BNP", "BL", "BNL",
|
||
"BM", "BNM", "BO", "BC",
|
||
"B", "BR",
|
||
"BALR","BTCR","BFCR",
|
||
"NHR", "CLHR","OHR", "XHR",
|
||
"LHR", "AHR", "SHR",
|
||
"MHR", "DHR", "ACHR","SCHR",
|
||
"LER", "CER", "AER", "SER",
|
||
"MER", "DER",
|
||
"BAL", "BTC", "BFC",
|
||
"NH", "CLH", "OH", "XH",
|
||
"LH", "AH", "SH",
|
||
"MH", "DH", "ACH", "SCH",
|
||
"STE",
|
||
"LE", "CE", "AE", "SE",
|
||
"ME", "DE",
|
||
"STBR","LBR",
|
||
"WBR", "RBR",
|
||
"WDR", "RDR",
|
||
"SSR", "OCR", "AIR",
|
||
"BXH", "BXLE","LPSW",
|
||
"NHI", "CLHI","OHI", "XHI",
|
||
"LHI", "AHI", "SHI",
|
||
"SRHL","SLHL","SRHA","SLHA",
|
||
"STM", "LM", "STB", "LB",
|
||
"AL", "WB", "RB",
|
||
"WD", "RD",
|
||
"SS", "OC", "AI",
|
||
NULL };
|
||
|
||
static const int32 opc_val[] = {
|
||
0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X,
|
||
0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X,
|
||
0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4280+I_X,
|
||
0x4300+I_X, 0x0300+I_R,
|
||
0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR,
|
||
0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR,
|
||
0x0800+I_RR, 0x0A00+I_RR, 0x0B00+I_RR,
|
||
0x0C00+I_RR, 0x0D00+I_RR, 0x0E00+I_RR, 0x0F00+I_RR,
|
||
0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF,
|
||
0x2C00+I_FF, 0x2D00+I_FF,
|
||
0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX,
|
||
0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX,
|
||
0x4800+I_RX, 0x4A00+I_RX, 0x4B00+I_RX,
|
||
0x4C00+I_RX, 0x4D00+I_RX, 0x4E00+I_RX, 0x4F00+I_RX,
|
||
0x6000+I_FX,
|
||
0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX,
|
||
0x6C00+I_FX, 0x6D00+I_FX,
|
||
0x9200+I_RR, 0x9300+I_RR,
|
||
0x9600+I_RR, 0x9700+I_RR,
|
||
0x9A00+I_RR, 0x9B00+I_RR,
|
||
0x9D00+I_RR, 0x9E00+I_RR, 0x9F00+I_RR,
|
||
0xC000+I_RX, 0xC100+I_RX, 0xC200+I_RX,
|
||
0xC400+I_RX, 0xC500+I_RX, 0xC600+I_RX, 0xC700+I_RX,
|
||
0xC800+I_RX, 0xCA00+I_RX, 0xCB00+I_RX,
|
||
0xCC00+I_RX, 0xCD00+I_RX, 0xCE00+I_RX, 0xCF00+I_RX,
|
||
0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX,
|
||
0xD500+I_RX, 0xD600+I_RX, 0xD700+I_RX,
|
||
0xDA00+I_RX, 0xDB00+I_RX,
|
||
0xDD00+I_RX, 0xDE00+I_RX, 0xDF00+I_RX,
|
||
-1 };
|
||
|
||
/* Symbolic decode
|
||
|
||
Inputs:
|
||
*of = output stream
|
||
addr = current PC
|
||
*val = values to decode
|
||
*uptr = pointer to unit
|
||
sw = switches
|
||
Outputs:
|
||
return = if >= 0, error code
|
||
if < 0, number of extra words retired
|
||
*/
|
||
|
||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||
UNIT *uptr, int32 sw)
|
||
{
|
||
int32 i, j, c1, c2, inst, r1, r2;
|
||
|
||
c1 = (val[0] >> 8) & 0x3F; /* big endian */
|
||
c2 = val[0] & 0177;
|
||
if (sw & SWMASK ('A')) { /* ASCII? */
|
||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||
return SCPE_OK; }
|
||
if (sw & SWMASK ('C')) { /* character? */
|
||
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
|
||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||
return SCPE_OK; }
|
||
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||
|
||
inst = val[0];
|
||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||
r1 = (val[0] >> 4) & 0xF;
|
||
r2 = val[0] & 0xF;
|
||
switch (j) { /* case on class */
|
||
case I_V_MR: /* mask-register */
|
||
fprintf (of, "%s %-X,R%-X", opcode[i], r1, r2);
|
||
return SCPE_OK;
|
||
case I_V_RR: /* register-register */
|
||
case I_V_FF: /* floating-floating */
|
||
fprintf (of, "%s R%-X,R%-X", opcode[i], r1, r2);
|
||
return SCPE_OK;
|
||
case I_V_R: /* register */
|
||
fprintf (of, "%s R%-X", opcode[i], r2);
|
||
return SCPE_OK;
|
||
case I_V_MX: /* mask-memory */
|
||
fprintf (of, "%s %-X,%-X", opcode[i], r1, val[1]);
|
||
break;
|
||
case I_V_RX: /* register-memory */
|
||
case I_V_FX: /* floating-memory */
|
||
fprintf (of, "%s R%-X,%-X", opcode[i], r1, val[1]);
|
||
break;
|
||
case I_V_X: /* memory */
|
||
fprintf (of, "%s %-X", opcode[i], val[1]);
|
||
break; } /* end case */
|
||
if (r2) fprintf (of, "(R%-X)", r2);
|
||
return -1; } /* end if */
|
||
} /* end for */
|
||
return SCPE_ARG; /* no match */
|
||
}
|
||
|
||
/* Register number
|
||
|
||
Inputs:
|
||
*cptr = pointer to input string
|
||
mchar = match character
|
||
regflt = false for integer, true for floating
|
||
Outputs:
|
||
rnum = output register number, -1 if error
|
||
*/
|
||
|
||
int32 get_reg (char *cptr, char mchar, t_bool regflt)
|
||
{
|
||
int32 reg = -1;
|
||
|
||
if ((*cptr == 'R') || (*cptr == 'r')) cptr++;
|
||
if (*(cptr + 1) != mchar) return reg;
|
||
if ((*cptr >= '0') && (*cptr <= '9')) reg = *cptr - '0';
|
||
else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10;
|
||
else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10;
|
||
if (regflt && (reg & 1)) return -1;
|
||
return reg;
|
||
}
|
||
|
||
/* Symbolic input
|
||
|
||
Inputs:
|
||
*cptr = pointer to input string
|
||
addr = current PC
|
||
*uptr = pointer to unit
|
||
*val = pointer to output values
|
||
sw = switches
|
||
Outputs:
|
||
status = > 0 error code
|
||
<= 0 -number of extra words
|
||
*/
|
||
|
||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||
{
|
||
int32 i, j, r1, r2;
|
||
t_bool regflt;
|
||
char *tptr, gbuf[CBUFSIZE];
|
||
|
||
regflt = FALSE; /* assume int reg */
|
||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||
val[0] = (t_value) cptr[0];
|
||
return SCPE_OK; }
|
||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||
val[0] = ((t_value) cptr[0] << 8) + (t_value) cptr[1];
|
||
return SCPE_OK; }
|
||
|
||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||
if (opcode[i] == NULL) return SCPE_ARG;
|
||
val[0] = opc_val[i] & 0xFFFF; /* get value */
|
||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||
switch (j) { /* case on class */
|
||
|
||
case I_V_FF: /* float-float */
|
||
regflt = TRUE; /* fall thru */
|
||
case I_V_MR: case I_V_RR: /* mask/reg-register */
|
||
cptr = get_glyph (cptr, gbuf, ','); /* get register 1 */
|
||
if ((r1 = get_reg (gbuf, 0, regflt)) < 0) return SCPE_ARG;
|
||
val[0] = val[0] | (r1 << 4); /* fall thru for reg 2 */
|
||
|
||
case I_V_R: /* register */
|
||
cptr = get_glyph (cptr, gbuf, 0); /* get r2 */
|
||
if ((r2 = get_reg (gbuf, 0, regflt)) < 0) return SCPE_ARG;
|
||
val[0] = val[0] | r2;
|
||
if (*cptr != 0) return SCPE_ARG;
|
||
return SCPE_OK;
|
||
|
||
case I_V_FX: /* float-memory */
|
||
regflt = TRUE; /* fall thru */
|
||
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
||
cptr = get_glyph (cptr, gbuf, ','); /* get register 1 */
|
||
if ((r1 = get_reg (gbuf, 0, regflt)) < 0) return SCPE_ARG;
|
||
val[0] = val[0] | (r1 << 4); /* fall thru for memory */
|
||
|
||
case I_V_X: /* memory */
|
||
val[1] = strtoul (cptr, &tptr, 16);
|
||
if (cptr == tptr) return SCPE_ARG;
|
||
if (*tptr == 0) return -1;
|
||
if ((*tptr != '(') || (*(tptr + 4) != 0)) return SCPE_ARG;
|
||
if ((r2 = get_reg (tptr + 1, ')', FALSE)) < 0) return SCPE_ARG;
|
||
val[0] = val[0] | r2;
|
||
return -1; } /* end case */
|
||
}
|