The B5500 simulator supports the following peripherals. Two CPUs with between 4K and 32K of memory. The second CPU can be enabled with "set cpu1 enable". "set cpu1 disable" disables the second CPU. Up to 4 floating IO channels. Individual channels can be enabled with "set io# enable", or "set io# disable". There are two card readers. The second reader is disabled by default. There is one Card Punch. The Card reader and Card Punch support the following options: set cr format= auto - will automatically determine the format based on the text it recieves. text Text based cards. Tabs are converted to the correct number of spaces. A record of ~raw octal will enter a binary card. ~eor will enter a 7/8/9 punch in column 1. ~eof will enter a 6/7/9 punch in column 1. ~eoi will enter a 6/7/8/9 punch in column 1. ~~ will enter a ~ as the first character. bin Binary Card format: Each record 160 characters. First characters 6789---- Second character 21012345 111 Top 4 bits of second character are 0. It is unlikely that any other format could look like this. bcd BCD Format: Each record variable length (80 chars or less). Record mark has bit 7 set. Bit 6 is even parity. Bits 5-0 are character. cbn CBN Format: Each record 160 charaters. First char has bit 7 set. Rest set to 0. Bit 6 is odd parity. Bit 5-0 of first character are top 6 bits of card. Bit 5-0 of second character are lower 6 bits of card. For punch format of auto if the card can't be converted to text it is output as a raw record. There are two line printers, the second one is disabled by default. The LP supports the option "set lp# linesperpage=#" which determines when the printer will force out a page break. There are up to 16 mag tape drives, the format is controlled by the standard simh format control for tapes. These are 6 bit tapes, 1 character per record with parity. Units 8-16 are disabled by default. There are up to two drum units DR0 and DR1. These can either be attached to a file or set to AUXMEM. Setting to AUXMEM causes them to exist only during the given simh run. Setting back to DRUM will clear whatever was stored on the drum. To enable use of DRUM on XV the following options should be turned on "DRA,DRB,CODEOLAY,DATAOLAY". MCP will then use the drum as a overlay device instead of the disk system. Disks can be attached to the various ESU's, ESU0-9 are on DKA by default, ESU10-19 are on DKB. If "set dk1 dfx" is set, then ESU10-19 are not used and the disks are shared by both DKA and DKB. To use more then 10 ESU's in a non shared mode, a new version of MCP must be created. MCP must be compiled with DFX option set to false. For MCP XV DKBNODFX must also be set to true. ESU units can be set to MODI or MODIB. MODIB will double the size of the drive. The DTC can be attached to a telnet port with "attach dtc #" to enable dialup access to the sim. The loader card for the card reader is: ~raw0104441100204231524012004000004444550211002041317700000000000024045303040243 00050000006501004131011041310055005500000062005042310000006600304231000000720010 42310000007675610165001002310010413100040107202500440106202533554061256520252265 20251765202514655355536117650000004401062025155522610165225572610465044101160500 4131 This card should be all in one line.
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(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, char *cptr, 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(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;
|
||
}
|