These changes facilitate more robust parameter type checking and helps to identify unexpected coding errors. Most simulators can now also be compiled with a C++ compiler without warnings. Additionally, these changes have also been configured to facilitate easier backporting of simulator and device simulation modules to run under the simh v3.9+ SCP framework.
541 lines
22 KiB
C
541 lines
22 KiB
C
/* b5500_sys.c: Burroughs 5500 Simulator system interface.
|
||
|
||
Copyright (c) 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 "sim_defs.h"
|
||
#include "b5500_defs.h"
|
||
#include "sim_card.h"
|
||
#include <ctype.h>
|
||
|
||
t_stat parse_sym(CONST char *cptr, t_addr addr, UNIT * uptr, t_value * val, int32 sw);
|
||
|
||
/* 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[] = "B5500";
|
||
|
||
REG *sim_PC = &cpu_reg[0];
|
||
|
||
int32 sim_emax = 1;
|
||
|
||
DEVICE *sim_devices[] = {
|
||
&cpu_dev,
|
||
&chan_dev,
|
||
#if NUM_DEVS_CDR > 0
|
||
&cdr_dev,
|
||
#endif
|
||
#if NUM_DEVS_CDP > 0
|
||
&cdp_dev,
|
||
#endif
|
||
#if NUM_DEVS_LPR > 0
|
||
&lpr_dev,
|
||
#endif
|
||
#if NUM_DEVS_CON > 0
|
||
&con_dev,
|
||
#endif
|
||
#if NUM_DEVS_MT > 0
|
||
&mt_dev,
|
||
#endif
|
||
#if NUM_DEVS_DR > 0
|
||
&drm_dev,
|
||
#endif
|
||
#if NUM_DEVS_DSK > 0
|
||
&esu_dev,
|
||
&dsk_dev,
|
||
#endif
|
||
#if NUM_DEVS_DTC > 0
|
||
&dtc_dev,
|
||
#endif
|
||
NULL
|
||
};
|
||
|
||
/* Simulator stop codes */
|
||
const char *sim_stop_messages[] = {
|
||
0,
|
||
};
|
||
|
||
/* Simulator debug controls */
|
||
DEBTAB dev_debug[] = {
|
||
{"CMD", DEBUG_CMD, "Show command execution to devices"},
|
||
{"DATA", DEBUG_DATA, "Show data transfers"},
|
||
{"DETAIL", DEBUG_DETAIL, "Show details about device"},
|
||
{"EXP", DEBUG_EXP, "Show exception information"},
|
||
{0, 0}
|
||
};
|
||
|
||
|
||
uint8 parity_table[64] = {
|
||
/* 0 1 2 3 4 5 6 7 */
|
||
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
||
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000,
|
||
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000,
|
||
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
||
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000,
|
||
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
||
0000, 0100, 0100, 0000, 0100, 0000, 0000, 0100,
|
||
0100, 0000, 0000, 0100, 0000, 0100, 0100, 0000
|
||
};
|
||
|
||
uint8 mem_to_ascii[64] = {
|
||
/* x0 x1 x2 x3 x4 x5 x6 x7 */
|
||
'0', '1', '2', '3', '4', '5', '6', '7', /* 0x */
|
||
'8', '9', '#', '@', '?', ':', '>', '}', /* 1x */
|
||
'+', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 2x */
|
||
'H', 'I', '.', '[', '&', '(', '<', '~', /* 3x */
|
||
'|', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 4x */
|
||
'Q', 'R', '$', '*', '-', ')', ';', '{', /* 5x */
|
||
' ', '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 6x */
|
||
'Y', 'Z', ',', '%', '!', '=', ']', '"' /* 7x */
|
||
};
|
||
|
||
const char con_to_ascii[64] = {
|
||
'?', '1', '2', '3', '4', '5', '6', '7',
|
||
'8', '9', '0', '#', '@', ':', '>', '}', /* 17 = box */
|
||
' ', '/', 'S', 'T', 'U', 'V', 'W', 'X',
|
||
'Y', 'Z', '!', ',', '%', '=', ']', '"',
|
||
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||
'Q', 'R', '|', '$', '*', ')', ';', '{', /* 57 = triangle */
|
||
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||
'H', 'I', '+', '.', '[', '(', '<', '~', /* 37 = stop code */
|
||
}; /* 72 = rec mark */
|
||
/* 75 = squiggle, 77 = del */
|
||
|
||
const char ascii_to_con[128] = {
|
||
/* Control */
|
||
-1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */
|
||
/* Control */
|
||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||
/* Control */
|
||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||
/* Control */
|
||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||
/*sp ! " # $ % & ' */
|
||
020, 032, 037, 013, 053, 017, 060, 014, /* 40 - 77 */
|
||
/* ( ) * + , - . / */
|
||
075, 055, 054, 072, 033, 040, 073, 021,
|
||
/* 0 1 2 3 4 5 6 7 */
|
||
012, 001, 002, 003, 004, 005, 006, 007,
|
||
/* 8 9 : ; < = > ? */
|
||
010, 011, 015, 056, 076, 035, 016, 000,
|
||
/* @ A B C D E F G */
|
||
014, 061, 062, 063, 064, 065, 066, 067, /* 100 - 137 */
|
||
/* H I J K L M N O */
|
||
070, 071, 041, 042, 043, 044, 045, 046,
|
||
/* P Q R S T U V W */
|
||
047, 050, 051, 022, 023, 024, 025, 026,
|
||
/* X Y Z [ \ ] ^ _ */
|
||
027, 030, 031, 075, 036, 055, 057, 000,
|
||
/* ` a b c d e f g */
|
||
035, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */
|
||
/* h i j k l m n o */
|
||
070, 071, 041, 042, 043, 044, 045, 046,
|
||
/* p q r s t u v w */
|
||
047, 050, 051, 022, 023, 024, 025, 026,
|
||
/* x y z { | } ~ del*/
|
||
027, 030, 031, 057, 077, 017, -1, -1
|
||
};
|
||
|
||
|
||
/* Load a card image file into memory. */
|
||
|
||
t_stat
|
||
sim_load(FILE * fileref, CONST char *cptr, CONST char *fnam, int flag)
|
||
{
|
||
/* Currently not implimented until I know format of load files */
|
||
return SCPE_NOFNC;
|
||
}
|
||
|
||
#define TYPE_A 1 /* Full 12 bit opcode */
|
||
#define TYPE_B 2 /* 6 Bit Opcode with 6 bit field */
|
||
#define TYPE_C 3 /* 8 Bit opcode with 4 bit field */
|
||
#define TYPE_D 4 /* 2 bit opcode, 10 bit field */
|
||
|
||
/* Opcodes */
|
||
t_opcode word_ops[] = {
|
||
/* Word mode opcodes */
|
||
WMOP_LITC, TYPE_D, "LITC", /* Load literal */
|
||
WMOP_OPDC, TYPE_D, "OPDC", /* Load operand */
|
||
WMOP_DESC, TYPE_D, "DESC", /* Load Descriptor */
|
||
WMOP_DEL, TYPE_A, "DEL", /* Delete top of stack */
|
||
WMOP_NOP, TYPE_A, "NOP", /* Nop operation */
|
||
WMOP_XRT, TYPE_A, "XRT", /* Set Variant */
|
||
WMOP_ADD, TYPE_A, "ADD", /* Add */
|
||
WMOP_DLA, TYPE_A, "DLA", /* Double Precision Add */
|
||
WMOP_PRL, TYPE_A, "PRL", /* Program Release */
|
||
WMOP_LNG, TYPE_A, "LNG", /* Logical Negate */
|
||
WMOP_CID, TYPE_A, "CID", /* Conditional Integer Store Destructive */
|
||
WMOP_GEQ, TYPE_A, "GEQ", /* B greater than or equal to A */
|
||
WMOP_BBC, TYPE_A, "BBC", /* Branch Backward Conditional */
|
||
WMOP_BRT, TYPE_A, "BRT", /* Branch Return */
|
||
WMOP_INX, TYPE_A, "INX", /* Index */
|
||
WMOP_ITI, TYPE_A, "ITI", /* Interrogate interrupt */
|
||
WMOP_LOR, TYPE_A, "LOR", /* Logical Or */
|
||
WMOP_CIN, TYPE_A, "CIN", /* Conditional Integer Store non-destructive */
|
||
WMOP_GTR, TYPE_A, "GTR", /* B Greater than A */
|
||
WMOP_BFC, TYPE_A, "BFC", /* Branch Forward Conditional */
|
||
WMOP_RTN, TYPE_A, "RTN", /* Return normal */
|
||
WMOP_COC, TYPE_A, "COC", /* Construct Operand Call */
|
||
WMOP_SUB, TYPE_A, "SUB", /* Subtract */
|
||
WMOP_DLS, TYPE_A, "DLS", /* Double Precision Subtract */
|
||
WMOP_MUL, TYPE_A, "MUL", /* Multiply */
|
||
WMOP_DLM, TYPE_A, "DLM", /* Double Precision Multiply */
|
||
WMOP_RTR, TYPE_A, "RTR", /* Read Timer */
|
||
WMOP_LND, TYPE_A, "LND", /* Logical And */
|
||
WMOP_STD, TYPE_A, "STD", /* B Store Destructive */
|
||
WMOP_NEQ, TYPE_A, "NEQ", /* B Not equal to A */
|
||
WMOP_SSN, TYPE_A, "SSN", /* Set Sign Bit */
|
||
WMOP_XIT, TYPE_A, "XIT", /* Exit */
|
||
WMOP_MKS, TYPE_A, "MKS", /* Mark Stack */
|
||
WMOP_DIV, TYPE_A, "DIV", /* Divide */
|
||
WMOP_DLD, TYPE_A, "DLD", /* Double Precision Divide */
|
||
WMOP_COM, TYPE_A, "COM", /* Communication operator */
|
||
WMOP_LQV, TYPE_A, "LQV", /* Logical Equivalence */
|
||
WMOP_SND, TYPE_A, "SND", /* B Store Non-destructive */
|
||
WMOP_XCH, TYPE_A, "XCH", /* Exchange */
|
||
WMOP_CHS, TYPE_A, "CHS", /* Change sign bit */
|
||
WMOP_RTS, TYPE_A, "RTS", /* Return Special */
|
||
WMOP_CDC, TYPE_A, "CDC", /* Construct descriptor call */
|
||
WMOP_FTC, TYPE_A, "FTC", /* Transfer F Field to Core Field */
|
||
WMOP_MOP, TYPE_A, "MOP", /* Reset Flag bit */
|
||
WMOP_LOD, TYPE_A, "LOD", /* Load */
|
||
WMOP_DUP, TYPE_A, "DUP", /* Duplicate */
|
||
WMOP_TOP, TYPE_A, "TOP", /* Test Flag Bit */
|
||
WMOP_IOR, TYPE_A, "IOR", /* I/O Release */
|
||
WMOP_LBC, TYPE_A, "LBC", /* Word Branch Backward Conditional */
|
||
WMOP_SSF, TYPE_A, "SSF", /* Set or Store S or F registers */
|
||
WMOP_HP2, TYPE_A, "HP2", /* Halt P2 */
|
||
WMOP_LFC, TYPE_A, "LFC", /* Word Branch Forward Conditional */
|
||
WMOP_ZP1, TYPE_A, "ZP1", /* Conditional Halt */
|
||
WMOP_TUS, TYPE_A, "TUS", /* Interrogate Peripheral Status */
|
||
WMOP_LLL, TYPE_A, "LLL", /* Link List Look-up */
|
||
WMOP_IDV, TYPE_A, "IDV", /* Integer Divide Integer */
|
||
WMOP_SFI, TYPE_A, "SFI", /* Store for Interrupt */
|
||
WMOP_SFT, TYPE_A, "SFT", /* Store for Test */
|
||
WMOP_FTF, TYPE_A, "FTF", /* Transfer F Field to F Field */
|
||
WMOP_MDS, TYPE_A, "MDS", /* Set Flag Bit */
|
||
WMOP_IP1, TYPE_A, "IP1", /* Initiate P1 */
|
||
WMOP_ISD, TYPE_A, "ISD", /* Interger Store Destructive */
|
||
WMOP_LEQ, TYPE_A, "LEQ", /* B Less Than or Equal to A */
|
||
WMOP_BBW, TYPE_A, "BBW", /* Banch Backward Conditional */
|
||
WMOP_IP2, TYPE_A, "IP2", /* Initiate P2 */
|
||
WMOP_ISN, TYPE_A, "ISN", /* Integer Store Non-Destructive */
|
||
WMOP_LSS, TYPE_A, "LSS", /* B Less Than A */
|
||
WMOP_BFW, TYPE_A, "BFW", /* Branch Forward Unconditional */
|
||
WMOP_IIO, TYPE_A, "IIO", /* Initiate I/O */
|
||
WMOP_EQL, TYPE_A, "EQL", /* B Equal A */
|
||
WMOP_SSP, TYPE_A, "SSP", /* Reset Sign Bit */
|
||
WMOP_CMN, TYPE_A, "CMN", /* Enter Character Mode In Line */
|
||
WMOP_IFT, TYPE_A, "IFT", /* Test Initiate */
|
||
WMOP_CTC, TYPE_A, "CTC", /* Transfer Core Field to Core Field */
|
||
WMOP_LBU, TYPE_A, "LBU", /* Word Branch Backward Unconditional */
|
||
WMOP_LFU, TYPE_A, "LFU", /* Word Branch Forward Unconditional */
|
||
WMOP_TIO, TYPE_A, "TIO", /* Interrogate I/O Channels */
|
||
WMOP_RDV, TYPE_A, "RDV", /* Remainder Divide */
|
||
WMOP_FBS, TYPE_A, "FBS", /* Flag Bit Search */
|
||
WMOP_CTF, TYPE_A, "CTF", /* Transfer Core Field to F Field */
|
||
WMOP_ISO, TYPE_B, "ISO", /* Variable Field Isolate XX */
|
||
WMOP_CBD, TYPE_C, "CBD", /* Non-Zero Field Branch Backward Destructive Xy */
|
||
WMOP_CBN, TYPE_C, "CBN", /* Non-Zero Field Branch Backward Non-Destructive Xy */
|
||
WMOP_CFD, TYPE_C, "CFD", /* Non-Zero Field Branch Forward Destructive Xy */
|
||
WMOP_CFN, TYPE_B, "CFN", /* Non-Zero Field Branch Forward Non-Destructive Xy */
|
||
WMOP_DIA, TYPE_B, "DIA", /* Dial A XX */
|
||
WMOP_DIB, TYPE_B, "DIB", /* Dial B XX Upper 6 not Zero */
|
||
WMOP_TRB, TYPE_B, "TRB", /* Transfer Bits XX */
|
||
WMOP_FCL, TYPE_B, "FCL", /* Compare Field Low XX */
|
||
WMOP_FCE, TYPE_B, "FCE", /* Compare Field Equal XX */
|
||
{0, 0, NULL},
|
||
};
|
||
|
||
t_opcode char_ops[] = {
|
||
/* Character Mode */
|
||
CMOP_EXC, TYPE_A, "EXC", /* Exit Character Mode */
|
||
CMOP_CMX, TYPE_A, "CMX", /* Exit Character Mode In Line */
|
||
CMOP_BSD, TYPE_B, "BSD", /* Skip Bit Destiniation */
|
||
CMOP_BSS, TYPE_B, "BSS", /* SKip Bit Source */
|
||
CMOP_RDA, TYPE_B, "RDA", /* Recall Destination Address */
|
||
CMOP_TRW, TYPE_B, "TRW", /* Transfer Words */
|
||
CMOP_SED, TYPE_B, "SED", /* Set Destination Address */
|
||
CMOP_TDA, TYPE_B, "TDA", /* Transfer Destination Address */
|
||
CMOP_TBN, TYPE_B, "TBN", /* Transfer Blanks for Non-Numerics */
|
||
WMOP_ITI, TYPE_A, "ITI", /* Interrogate interrupt */
|
||
WMOP_SFI, TYPE_A, "SFI", /* Store for Interrupt */
|
||
WMOP_SFT, TYPE_A, "SFT", /* Store for Test */
|
||
WMOP_ZP1, TYPE_A, "ZP1", /* Conditional Halt */
|
||
WMOP_HP2, TYPE_A, "HP2", /* Halt P2 */
|
||
CMOP_SDA, TYPE_B, "SDA", /* Store Destination Address */
|
||
CMOP_SSA, TYPE_B, "SSA", /* Store Source Address */
|
||
CMOP_SFD, TYPE_B, "SFD", /* Skip Forward Destination */
|
||
CMOP_SRD, TYPE_B, "SRD", /* Skip Reverse Destination */
|
||
CMOP_SES, TYPE_B, "SES", /* Set Source Address */
|
||
CMOP_TEQ, TYPE_B, "TEQ", /* Test for Equal */
|
||
CMOP_TNE, TYPE_B, "TNE", /* Test for Not-Equal */
|
||
CMOP_TEG, TYPE_B, "TEG", /* Test for Greater Or Equal */
|
||
CMOP_TGR, TYPE_B, "TGR", /* Test For Greater */
|
||
CMOP_SRS, TYPE_B, "SRS", /* Skip Reverse Source */
|
||
CMOP_SFS, TYPE_B, "SFS", /* Skip Forward Source */
|
||
CMOP_TEL, TYPE_B, "TEL", /* Test For Equal or Less */
|
||
CMOP_TLS, TYPE_B, "TLS", /* Test For Less */
|
||
CMOP_TAN, TYPE_B, "TAN", /* Test for Alphanumeric */
|
||
CMOP_BIT, TYPE_B, "BIT", /* Test Bit */
|
||
CMOP_INC, TYPE_B, "INC", /* Increase Tally */
|
||
CMOP_STC, TYPE_B, "STC", /* Store Tally */
|
||
CMOP_SEC, TYPE_B, "SEC", /* Set Tally */
|
||
CMOP_CRF, TYPE_B, "CRF", /* Call repeat Field */
|
||
CMOP_JNC, TYPE_B, "JNC", /* Jump Out Of Loop Conditional */
|
||
CMOP_JFC, TYPE_B, "JFC", /* Jump Forward Conditional */
|
||
CMOP_JNS, TYPE_B, "JNS", /* Jump out of loop unconditional */
|
||
CMOP_JFW, TYPE_B, "JFW", /* Jump Forward Unconditional */
|
||
CMOP_RCA, TYPE_B, "RCA", /* Recall Control Address */
|
||
CMOP_ENS, TYPE_B, "ENS", /* End Loop */
|
||
CMOP_BNS, TYPE_B, "BNS", /* Begin Loop */
|
||
CMOP_RSA, TYPE_B, "RSA", /* Recall Source Address */
|
||
CMOP_SCA, TYPE_B, "SCA", /* Store Control Address */
|
||
CMOP_JRC, TYPE_B, "JRC", /* Jump Reverse Conditional */
|
||
CMOP_TSA, TYPE_B, "TSA", /* Transfer Source Address */
|
||
CMOP_JRV, TYPE_B, "JRV", /* Jump Reverse Unconditional */
|
||
CMOP_CEQ, TYPE_B, "CEQ", /* Compare Equal */
|
||
CMOP_CNE, TYPE_B, "CNE", /* COmpare for Not Equal */
|
||
CMOP_CEG, TYPE_B, "CEG", /* Compare For Greater Or Equal */
|
||
CMOP_CGR, TYPE_B, "CGR", /* Compare For Greater */
|
||
CMOP_BIS, TYPE_B, "BIS", /* Set Bit */
|
||
CMOP_BIR, TYPE_B, "BIR", /* Reet Bit */
|
||
CMOP_OCV, TYPE_B, "OCV", /* Output Convert */
|
||
CMOP_ICV, TYPE_B, "ICV", /* Input Convert */
|
||
CMOP_CEL, TYPE_B, "CEL", /* Compare For Equal or Less */
|
||
CMOP_CLS, TYPE_B, "CLS", /* Compare for Less */
|
||
CMOP_FSU, TYPE_B, "FSU", /* Field Subtract */
|
||
CMOP_FAD, TYPE_B, "FAD", /* Field Add */
|
||
CMOP_TRP, TYPE_B, "TRP", /* Transfer Program Characters */
|
||
CMOP_TRN, TYPE_B, "TRN", /* Transfer Numeric */
|
||
CMOP_TRZ, TYPE_B, "TRZ", /* Transfer Zones */
|
||
CMOP_TRS, TYPE_B, "TRS", /* Transfer Source Characters */
|
||
{0, 0, NULL},
|
||
};
|
||
|
||
|
||
/* Print out an instruction */
|
||
void
|
||
print_opcode(FILE * of, t_value val, t_opcode * tab)
|
||
{
|
||
uint16 op;
|
||
|
||
op = val;
|
||
while (tab->name != NULL) {
|
||
switch(tab->type) {
|
||
case TYPE_A:
|
||
if (op != tab->op)
|
||
break;
|
||
fputs(tab->name, of);
|
||
fputs(" ",of);
|
||
return;
|
||
case TYPE_B:
|
||
if ((op & 077) != tab->op)
|
||
break;
|
||
fputs(tab->name, of);
|
||
fputc(' ',of);
|
||
fputc(' ',of);
|
||
fprint_val(of, (val >> 6), 8, 6, 0);
|
||
fputs(" ",of);
|
||
return;
|
||
case TYPE_C:
|
||
if ((op & 0377) != tab->op)
|
||
break;
|
||
fputs(tab->name, of);
|
||
fputc(' ',of);
|
||
fprint_val(of, (val >> 8), 8, 4, 0);
|
||
fputs(" ",of);
|
||
return;
|
||
case TYPE_D:
|
||
if ((op & 03) != tab->op)
|
||
break;
|
||
fputs(tab->name, of);
|
||
fputc(' ',of);
|
||
fprint_val(of, (val >> 2), 8, 10, 0);
|
||
fputc(' ',of);
|
||
return;
|
||
}
|
||
tab++;
|
||
}
|
||
fprintf(of, "*%04o uuo ", op);
|
||
}
|
||
|
||
/* 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)
|
||
{
|
||
t_value inst = *val;
|
||
int i;
|
||
|
||
fputc(' ', of);
|
||
fprint_val(of, inst, 8, 48, PV_RZRO);
|
||
|
||
if (sw & SWMASK('W')) { /* Word mode opcodes */
|
||
fputs(" ", of);
|
||
for (i = 36; i >= 0; i-=12) {
|
||
int op = (int)(inst >> i) & 07777;
|
||
print_opcode(of, op, word_ops);
|
||
}
|
||
}
|
||
if (sw & SWMASK('C')) { /* Char mode opcodes */
|
||
fputs(" ", of);
|
||
for (i = 36; i >= 0; i-=12) {
|
||
int op = (int)(inst >> i) & 07777;
|
||
print_opcode(of, op, char_ops);
|
||
}
|
||
}
|
||
if (sw & SWMASK('B')) { /* BCD mode */
|
||
fputs(" '", of);
|
||
for (i = 42; i >= 0; i-=6) {
|
||
int ch;
|
||
|
||
ch = (int)(inst >> i) & 077;
|
||
fputc(mem_to_ascii[ch], of);
|
||
}
|
||
fputc('\'', of);
|
||
}
|
||
if (sw & SWMASK('F')) { /* Floating point/Descriptor */
|
||
}
|
||
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;
|
||
int opr;
|
||
char opcode[100];
|
||
|
||
while (isspace(*cptr))
|
||
cptr++;
|
||
d = 0;
|
||
if (sw & (SWMASK('W')|SWMASK('C'))) {
|
||
t_opcode *op;
|
||
|
||
/* Grab opcode */
|
||
cptr = get_glyph(cptr, opcode, 0);
|
||
|
||
op = 0;
|
||
opr = -1;
|
||
if((op = find_opcode(opcode,
|
||
(SWMASK('W') ? word_ops : char_ops))) == 0) {
|
||
return SCPE_UNK;
|
||
}
|
||
|
||
while (*cptr == ' ' || *cptr == '\t')
|
||
cptr++;
|
||
/* Collect first argument if there is one */
|
||
while (*cptr >= '0' && *cptr <= '7')
|
||
opr = (opr << 3) + (*cptr++ - '0');
|
||
/* Skip blanks */
|
||
while (*cptr == ' ' || *cptr == '\t')
|
||
cptr++;
|
||
switch (op->type) {
|
||
case TYPE_A:
|
||
if (opr >= 0)
|
||
return SCPE_2MARG;
|
||
*val = op->op;
|
||
return SCPE_OK;
|
||
|
||
case TYPE_B:
|
||
if (opr < 0 || opr > 64)
|
||
return SCPE_ARG;
|
||
*val = (opr << 6) | op->op;
|
||
return SCPE_OK;
|
||
|
||
case TYPE_C:
|
||
if (opr < 0 || opr > 16)
|
||
return SCPE_ARG;
|
||
*val = (opr << 8) | op->op;
|
||
return SCPE_OK;
|
||
|
||
case TYPE_D:
|
||
if (opr < 0 || opr > 1024)
|
||
return SCPE_ARG;
|
||
*val = (opr << 2) | op->op;
|
||
return SCPE_OK;
|
||
}
|
||
} else if (sw & SWMASK('B')) {
|
||
i = 0;
|
||
while (*cptr != '\0' && i < 8) {
|
||
d <<= 6;
|
||
d |= (int)sim_ascii_to_six[0177 & *cptr];
|
||
cptr++;
|
||
i++;
|
||
}
|
||
d <<= 6 * (8 - i);
|
||
} else {
|
||
while (*cptr >= '0' && *cptr <= '7') {
|
||
d <<= 3;
|
||
d |= *cptr++ - '0';
|
||
}
|
||
}
|
||
*val = d;
|
||
return SCPE_OK;
|
||
|
||
/* Symbolic input, continued */
|
||
|
||
if (*cptr != 0)
|
||
return SCPE_ARG; /* junk at end? */
|
||
return SCPE_OK;
|
||
}
|