/* i650_defs.h: IBM 650 simulator definitions | |
Copyright (c) 2018, Roberto Sancho | |
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 | |
ROBERTO SANCHO 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" /* simulator defns */ | |
/* Simulator stop codes */ | |
#define STOP_HALT 1 /* HALT */ | |
#define STOP_IBKPT 2 /* breakpoint */ | |
#define STOP_UUO 3 /* invalid opcode */ | |
#define STOP_CARD 4 /* Stop on card reader/punch error (no card in hopper, read/punch failure, no cards, stop pressed on cdr/cdp*/ | |
#define STOP_PROG 5 /* Programmed stop */ | |
#define STOP_OV 6 /* Overflow stop */ | |
#define STOP_ERRO 7 /* Error in opcode execution: BRD in witch position tested not 8 or 9, TLU failure */ | |
#define STOP_ADDR 8 /* Address stop: Store attempt on addr 800X, address out of drum mem */ | |
/* Memory */ | |
#define MAXDRUMSIZE (4000) | |
#define DRUMSIZE ((int)(cpu_unit.capac % 10) * 1000) /* actual drum memory size */ | |
extern t_int64 DRUM[MAXDRUMSIZE]; | |
extern int DRUM_NegativeZeroFlag[MAXDRUMSIZE]; | |
extern char DRUM_Symbolic_Buffer[MAXDRUMSIZE * 80]; | |
extern t_int64 IOSync[10]; | |
extern int IOSync_NegativeZeroFlag[10]; | |
#define STOR (cpu_unit.flags & OPTION_STOR) | |
#define CNTRL (cpu_unit.flags & OPTION_CNTRL) | |
#define FAST (cpu_unit.flags & OPTION_FAST) | |
extern t_int64 IAS[60]; | |
extern int IAS_NegativeZeroFlag[60]; | |
extern int IAS_TimingRing; | |
extern int WriteAddr(int AR, t_int64 d, int NegZero); | |
extern int ReadAddr(int AR, t_int64 * d, int * NegZero); | |
extern CONST char * DecodeOpcode(t_int64 d, int * opcode, int * DA, int * IA); | |
/* digits contants */ | |
#define D10 (10000000000LL) // ten digits (10 zeroes) | |
#define D8 (100000000L) // eight digits (8 zeroes) | |
#define D4 (10000L) // four digits (4 zeroes) | |
/* Device information block */ | |
struct dib { | |
uint8 upc; /* Units per channel */ | |
uint32 (*cmd)(UNIT *up, uint16 cmd, uint16 dev);/* Issue command. */ | |
void (*ini)(UNIT *up, t_bool f); | |
}; | |
typedef struct dib DIB; | |
/* Debuging controls */ | |
#define DEBUG_CMD 0x0000010 /* Show device commands */ | |
#define DEBUG_DETAIL 0x0000020 /* Show details */ | |
#define DEBUG_EXP 0x0000040 /* Show error conditions */ | |
#define DEBUG_DATA 0x0000080 /* Show data details */ | |
extern DEBTAB dev_debug[]; | |
extern DEBTAB crd_debug[]; | |
/* Returns from read/write */ | |
#define DATA_OK 0 /* Data transfered ok */ | |
#define TIME_ERROR 1 /* Channel did not transfer last operation */ | |
#define END_RECORD 2 /* End of record */ | |
/* Returns from device commands */ | |
#define SCPE_BUSY (1) /* Device is active */ | |
#define SCPE_NOCARDS (2) /* No cards to read or ti write */ | |
/* Global device definitions */ | |
#ifdef CPANEL | |
extern DEVICE cp_dev; | |
#endif | |
// max number of cards in deck for carddeck internal command | |
#define MAX_CARDS_IN_DECK 10000 | |
#define MAX_CARDS_IN_READ_TAKE_HOPPER 10 | |
extern DIB cdr_dib; | |
extern DEVICE cdr_dev; | |
extern uint32 cdr_cmd(UNIT *, uint16, uint16); | |
extern UNIT cdr_unit[4]; | |
extern char ReadHopper[3 * MAX_CARDS_IN_READ_TAKE_HOPPER * 80]; | |
extern int ReadHopperLast[3]; | |
extern DIB cdp_dib; | |
extern DEVICE cdp_dev; | |
extern uint32 cdp_cmd(UNIT *, uint16, uint16); | |
extern UNIT cdp_unit[4]; | |
/* Device status information stored in u5 */ | |
#define URCSTA_ERR 0002 /* Error reading record */ | |
#define URCSTA_BUSY 0010 /* Device is busy */ | |
#define URCSTA_LOAD 01000 /* Load flag for 533 card reader */ | |
#define URCSTA_SOAPSYMB 02000 /* Get soap symbolic info when reading the card */ | |
extern struct card_wirings { | |
uint32 mode; | |
const char *name; | |
} wirings[]; | |
extern char digits_ascii[31]; | |
extern char mem_to_ascii[101]; | |
extern int ascii_to_NN(int ch); | |
extern uint16 ascii_to_hol[128]; | |
/* Generic devices common to all */ | |
extern DEVICE cpu_dev; | |
extern UNIT cpu_unit; | |
extern REG cpu_reg[]; | |
extern int cycle_time; | |
/* I/O Command codes */ | |
#define IO_RDS 1 /* Read record */ | |
#define IO_WRS 4 /* Write one record */ | |
extern const char *cpu_description(DEVICE *dptr); | |
/* Opcodes */ | |
// Instructions on Basic machine | |
#define OP_AABL 17 // Add absolute to lower accumulator | |
#define OP_AL 15 // Add to lower accumulator | |
#define OP_AU 10 // Add to upper accumulator | |
#define OP_BRNZ 45 // Branch on accumulator non-zero | |
#define OP_BRMIN 46 // Branch on minus accumulator | |
#define OP_BRNZU 44 // Branch on non-zero in upper accumulator | |
#define OP_BROV 47 // Branch on overflow | |
#define OP_BRD1 91 // Branch on 8 in distributor positions 1-10 | |
#define OP_BRD2 92 | |
#define OP_BRD3 93 | |
#define OP_BRD4 94 | |
#define OP_BRD5 95 | |
#define OP_BRD6 96 | |
#define OP_BRD7 97 | |
#define OP_BRD8 98 | |
#define OP_BRD9 99 | |
#define OP_BRD10 90 | |
#define OP_DIV 14 // Divide | |
#define OP_DIVRU 64 // Divide and reset upper accumulator | |
#define OP_LD 69 // Load distributor | |
#define OP_MULT 19 // Multiply | |
#define OP_NOOP 00 // No operation | |
#define OP_PCH 71 // Punch a card | |
#define OP_RD 70 // Read a card | |
#define OP_RAABL 67 // Reset accumulator and add absolute to lower accumulator | |
#define OP_RAL 65 // Reset accumulator and add to lower accumulator | |
#define OP_RAU 60 // Reset accumulator and add to upper accumulator | |
#define OP_RSABL 68 // Reset accumulator and subtract absolute from lower accumulator | |
#define OP_RSL 66 // Reset accumulator and subtract from lower accumulator | |
#define OP_RSU 61 // Reset accumulator and subtract from upper accumulator | |
#define OP_SLT 35 // Shift accumulator left | |
#define OP_SCT 36 // Shift accumulator left and count | |
#define OP_SRT 30 // Shift accumulator right | |
#define OP_SRD 31 // Shift accumulator right and round accumulator | |
#define OP_STOP 01 // Stop if console switch is set to stop, otherwise continue as a NO-OP | |
#define OP_STD 24 // Store distributor into memory | |
#define OP_STDA 22 // Store lower accumulator data address into distributor, then store distributor into memory | |
#define OP_STIA 23 // Store lower accumulator instruction address into distributor, then store distributor into memory | |
#define OP_STL 20 // Store lower accumulator into memory | |
#define OP_STU 21 // Store upper accumulator into memory | |
#define OP_SABL 18 // Subtract absolute from lower accumulator | |
#define OP_SL 16 // Subtract from lower accumulator | |
#define OP_SU 11 // Subtract from upper accumulator | |
#define OP_TLU 84 // Table lookup | |
// Instructions on Storage Unit | |
// opcodes for indexing | |
#define OP_AXA 50 // Add to index register A | |
#define OP_SXA 51 // Substract from index A | |
#define OP_RAA 80 // Reset Add Index A | |
#define OP_RSA 81 // Reset Substract Index A | |
#define OP_NZA 40 // Branch Non Zero Index A | |
#define OP_BMA 41 // Branch Minus Index A | |
#define OP_AXB 52 // Add to index register B | |
#define OP_SXB 53 // Substract from index B | |
#define OP_RAB 82 // Reset Add Index B | |
#define OP_RSB 83 // Reset Substract Index B | |
#define OP_NZB 42 // Branch Non Zero Index B | |
#define OP_BMB 43 // Branch Minus Index B | |
#define OP_AXC 58 // Add to index register C | |
#define OP_SXC 59 // Substract from index C | |
#define OP_RAC 88 // Reset Add Index C | |
#define OP_RSC 89 // Reset Substract Index C | |
#define OP_NZC 48 // Branch Non Zero Index C | |
#define OP_BMC 49 // Branch Minus Index C | |
// io for synchronizers 2 & 3 | |
#define OP_RC1 72 // Read Conditional sync 1 | |
#define OP_RD2 73 // Read Sync 2 | |
#define OP_WR2 74 // Write Sync 2 | |
#define OP_RC2 75 // Read Conditional Sync 2 | |
#define OP_RD3 76 // Read Sync 3 | |
#define OP_WR3 77 // Write Sync 3 | |
#define OP_RC3 78 // Read Conditional Sync 3 | |
// immediate access storage (ias) | |
#define OP_LIB 8 // Load IAS block | |
#define OP_LDI 9 // Load IAS | |
#define OP_SIB 28 // Store IAS Block | |
#define OP_STI 29 // Store IAS | |
#define OP_SET 27 // Set IAS Timing Ring | |
// floating point | |
#define OP_FAD 32 // Floating Add | |
#define OP_FSB 33 // Floating Subtract | |
#define OP_FMP 39 // Floating Multiply | |
#define OP_FDV 34 // Floating Divide | |
#define OP_UFA 02 // Unnormalized Floating Add | |
#define OP_FAM 37 // Floating Add Absolute (Magnitude) | |
#define OP_FSM 38 // Floating Subtract Absolute (Magnitude) | |
// Instructions on Control Unit | |
// tape | |
#define OP_RTN 04 // Read Tape Numeric | |
#define OP_RTA 05 // Read Tape Alphameric | |
#define OP_WTN 06 // Write Tape Numeric | |
#define OP_WTA 07 // Write Tape Alphameric | |
#define OP_RTC 03 // Read Tape for Checking | |
#define OP_NTS 25 // Branch no Tape Signal | |
#define OP_NEF 54 // Branch no End of File | |
#define OP_RWD 55 // Rewind Tape | |
#define OP_WTM 56 // Write Tape Mark | |
#define OP_BST 57 // Backspace Tape | |
// ramac disk | |
#define OP_SDS 85 // Seek Disk Storage | |
#define OP_RDS 86 // Read Disk Storage | |
#define OP_WDS 87 // Write Disk Storage | |
// inquiry stations | |
#define OP_BIN 26 // Branch on Inquiry | |
#define OP_RPY 79 // Reply on Inquiry | |
// Valid Data Address (DA) | |
#define vda_D 1 // 0000-1999 Drum | |
#define vda_A 2 // 8000-8003 Arithmetic unit registers (ACC Low & Hi), Distributor, Console Switches register | |
#define vda_I 4 // 8005-8007 Index Registers (IR) | |
#define vda_T 8 // 8010-8015 Tape address | |
#define vda_S 16 // 9000-9059 Immediate Access Storage (IAS) | |
#define vda_9000 32 // 9000 Only addr 9000 valid | |
#define vda_DAITS (vda_D | vda_A | vda_I | vda_T | vda_S ) | |
#define vda_DAIS (vda_D | vda_A | vda_I | vda_S ) | |
#define vda_DAS (vda_D | vda_A | vda_S ) | |
#define vda_DS (vda_D | vda_S ) | |
#define opReadDA 1 // opcode fetchs data from DA address | |
#define opWriteDA 2 // opcode write data to DA | |
#define opStorUnit 1 // opcode available if IBM 653 Storage Unit is present | |
#define opCntrlUnit 2 // opcode available if IBM 652 Control Unit is present | |
#define IL_RD1 1 // interlock on drum area 01-10/51-60 used in reading with RD1 | |
#define IL_WR1 2 // interlock on drum area 27-36/77-86 used in writing for WR1 | |
#define IL_RD23 3 // interlock on drum area 39-48/89-98 used in reading with RD2/RD3 | |
#define IL_WR23 4 // interlock on drum area 13-22/63-72 used in writing for WR2/WR3 | |
#define IL_IAS 5 // interlock on ias access | |
#define IL_array 6 // interlock array definition value | |
/* Symbol tables */ | |
typedef struct | |
{ | |
uint16 opbase; // opcode number | |
const char *name1; // opcode name as in operation manual | |
const char *name2; // opcode name as in soap | |
uint8 opRW; // =wDA, rDA or zero | |
int option; // =0 -> opcode in basic machine, =1 -> Opcode because Storage Unit, =2 -> Opcode because Control Unit | |
int validDA; // valid data address for this instruction | |
int opInterLock; // Interlock required by opcode | |
} | |
t_opcode; | |
extern t_opcode base_ops[100]; | |
#define NEGZERO_value 0x7fffFFFFffffFFFF | |
#define AccNegative (((AccNegativeZeroFlag) || (ACC[1]<0) || (ACC[0]<0)) ? 1:0) | |
#define AbsWord(d) ((d < 0) ? -d:d) | |
#define printfw(d,negzero) (int32) AbsWord(d/D4), (int32) AbsWord(d%D4), ((d<0) || (negzero)) ? '-':'+' | |
#define printfd printfw(DIST, DistNegativeZeroFlag) | |
#define printfa (int32) AbsWord(ACC[1]/D4),(int32) AbsWord(ACC[1]%D4), printfw(AbsWord(ACC[0]), AccNegative) | |
/* Standard control panel wiring for card read/punch/print */ | |
#define UNIT_CARD_WIRING ( 0xF00 << UNIT_V_CARD_MODE) | |
#define WIRING_8WORD ( 0x000 << UNIT_V_CARD_MODE) | |
#define WIRING_SOAP ( 0x100 << UNIT_V_CARD_MODE) | |
#define WIRING_IS ( 0x200 << UNIT_V_CARD_MODE) | |
#define WIRING_IT ( 0x300 << UNIT_V_CARD_MODE) | |
#define WIRING_FORTRANSIT ( 0x400 << UNIT_V_CARD_MODE) | |
#define UNIT_CARD_ECHO ( 0x1000 << UNIT_V_CARD_MODE) | |
#define UNIT_CARD_PRINT ( 0x2000 << UNIT_V_CARD_MODE) | |
/* Decimal helper functions */ | |
extern int Get_HiDigit(t_int64 d); | |
extern int Shift_Digits(t_int64 * d, int nDigits); | |
extern char * word_to_ascii(char * buf, int CharStart, int CharLen, t_int64 d); | |