/* 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; | |
} |