/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 24-Nov-85 | [1.108] Created * 12-Dec-85 | [1.174] Use tell_op to print data * 13-Dec-85 | [1.180] Implement single cycle options * 14-Dec-85 | [1.190] Added conditional branch dispatch table * 15-Dec-85 | [1.209] Implemented BCV, BC9 * 17-Dec-85 | [1.212] Added B_BAV * 30-Dec-85 | [1.283] Added tests to branch on I/O error indicator * 27-Jan-86 | [1.350] declare single_cycle decode * 25-Feb-86 | [1.379] include <> => include "" * 31-Jul-86 | [1.405] Made all chars unsigned * 10-Nov-91 | [1.428] converted to Microsoft C 6.0 * 18-Nov-91 | [1.428] memory.h => mem1401.h, avoid ANSI name * 07-Jan-95 | [1.600J] JRJ Implement Tape I/O branches *****************************************************************************/ #include #include #include "mem1401.h" #include "boolean.h" #include "btypes.h" #include "mach.h" #include "diag.h" #include "instr.h" #include "alerts.h" #include "alert.h" #include "logic.h" #include "switches.h" #include "poll.h" #include "ifetch.h" #include "button.h" #include "tape.h" #define B_B_f_complete single_cycle(i_B,B_f_complete) extern char * single_cycle_decode(); /***************************************************************************** 1401 Simulator Branch Instruction Branch (Two Addresses + d) -------------------------- Instruction format Mnemonic Op Code I-address B-address d-char -------- ------- --------- --------- ------ BCE B III BBB d Function: This instruction causes the single character at the B-address to be compared to the d-character. If it has the same bit configuration as the d-character, the program branches to the I-address, otherwise the program continues sequentially. The d-character can be any combination of the six BCD code bits (BA 8421) Word Marks: Word marks in the location tested have no effect on the operation. Address Registers After Operation: No Branch: I-Add A-Add B-Add NSI BI B-1 Branch I-Add A-Add B-Add NSI BI NSI Chaining: Note: Care must be taken if the specified d-character is also the same d-character than can test and reset an indicator OFF when it is used with a Bxxxd instruction. If the indicator is on during the execution of the Bxxxxxxd instruction, it is turned off. Branch (One Address + d) ------------------------ Instruction format Mnemonic Op Code I-address d-character -------- ------- --------- ----------- BIN B III d BC9 B III 9 channel 9 BCV B III @ channel 12 BLC B III A last card (SS A) BSS B III B SS B BSS B III C SS C BSS B III D SS D BSS B III E SS E BSS B III F SS F BSS B III G SS G BEF B III K+ End of reel BER B III L Tape transmission err BIN B III N Access inoperable BIN B III ?+ Reader err, ~I/O chk BIN B III !+ Punch err, ~I/O chk BIN B III Ø+ Printer err, ~I/O chk BIN B III * Inquiry clear BU B III / B != A BPB B III P Printer busy BIN B III Q Inquiry request BPCB B III R Printer carriage busy BE B III S B = A BL B III T B < A BH B III U B > A BIN B III V RW parity or RBchk BIN B III W Wrong length record BIN B III X Unequal addr compare BIN B III Y Any-disk-error BAV B III Z+ Overflow BIN B III %+ Processing check Function: The d-character specifies the indicator tested. If the indicator is on, the next instruction is taken from the I-address. If the indicator is off, the next sequential instruction is taken. The table above shows the d-characters and conditions they test. The indicators tested are not turned off by this instruction except as noted by the + following the d-character in the table. When carriage tape channels 9 or 12 are sensed, the corresponding indicators are turned on. These carriage channel indicators are turned off when any other carriage tape-channel is sense (refer to Notes in Control Carriage for other information). The next compare instruction turns off the compare indicators. Word Marks: Word marks are not affected. Note: See the notes for the branch-on-character-equal test, above. Address Registers After Operation: No branch I-Add A-Add B-Add ----- ----- ----- NSI BI dbb Branch I-Add A-Add B-Add ----- ----- ----- NSI BI NSI Branch (One Address) -------------------- Instruction format Mnemonic Op Code I-address -------- ------- --------- B B III Function: The instruction always causes a branch to the address specified by the I-address portion of the instruction. This unconditional branch operation is used to interrupt normal program flow and continue the program at some other point, without testing for specific conditions. Word Marks: A word mark must be associated with the core-storage position of the next I-address. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI BI NSI *****************************************************************************/ extern boolean B_uncond(unsigned char d); extern boolean B_illegal(unsigned char d); extern boolean B_nop(unsigned char d); extern boolean B_SS(unsigned char d); extern boolean B_BAV(unsigned char d); extern boolean B_GT(unsigned char d); extern boolean B_LT(unsigned char d); extern boolean B_EQ(unsigned char d); extern boolean B_NE(unsigned char d); extern boolean B_BCV(unsigned char d); extern boolean B_BC9(unsigned char d); extern boolean B_perr(unsigned char d); extern boolean B_EF(unsigned char d); extern boolean B_ER(unsigned char d); boolean (* dcodes[64])(unsigned char d) = { B_uncond, /* 0 - sp unconditional */ B_illegal, /* 1 - 1 illegal */ B_illegal, /* 2 - 2 illegal */ B_illegal, /* 3 - 3 illegal */ B_illegal, /* 4 - 4 illegal */ B_illegal, /* 5 - 5 illegal */ B_illegal, /* 6 - 6 illegal */ B_illegal, /* 7 - 7 illegal */ B_illegal, /* 8 - 8 illegal */ B_BC9, /* 9 - 9 printer ch 9 */ B_illegal, /* 10 - 0 illegal */ B_illegal, /* 11 - #= illegal */ B_BCV, /* 12 - @' printer ch 12 */ B_illegal, /* 13 - : illegal */ B_illegal, /* 14 - > illegal */ B_illegal, /* 15 - û illegal */ B_illegal, /* 16 - b illegal */ B_NE, /* 17 - / B != A */ B_EQ, /* 18 - S B = A */ B_LT, /* 19 - T B < A */ B_GT, /* 20 - U B > A */ B_illegal, /* 21 - V RW parity/RBchk */ B_illegal, /* 22 - W wrong len record */ B_illegal, /* 23 - X disk != addr */ B_illegal, /* 24 - Y any disk err */ B_BAV, /* 25 - Z overflow */ B_perr, /* 26 - Ø Printer err */ B_illegal, /* 27 - , illegal */ B_nop, /* 28 - %( Processor check */ B_illegal, /* 29 - ^ illegal */ B_illegal, /* 30 - \ illegal */ B_illegal, /* 31 - × illegal */ B_illegal, /* 32 - - illegal */ B_illegal, /* 33 - J illegal */ B_EF, /* 34 - K End of Reel */ B_ER, /* 35 - L Tape Xmit error */ B_illegal, /* 36 - M illegal */ B_illegal, /* 37 - N Access inoperable*/ B_illegal, /* 38 - O illegal */ B_nop, /* 39 - P printer busy */ B_illegal, /* 40 - Q Inquiry request */ B_nop, /* 41 - R Printer carr. bsy*/ B_perr, /* 42 - ! Punch err */ B_illegal, /* 43 - * Inquiry clear */ B_illegal, /* 44 - illegal */ B_illegal, /* 45 - ] illegal */ B_illegal, /* 46 - ; illegal */ B_illegal, /* 47 -  illegal */ B_illegal, /* 48 - &+ illegal */ B_SS, /* 49 - A Sense Switch A */ B_SS, /* 50 - B Sense Switch B */ B_SS, /* 51 - C Sense Switch C */ B_SS, /* 52 - D Sense Switch D */ B_SS, /* 53 - E Sense Switch E */ B_SS, /* 54 - F Sense Switch F */ B_SS, /* 55 - G Sense Switch G */ B_illegal, /* 56 - H illeagl */ B_illegal, /* 57 - I illegal */ B_perr, /* 58 - ? Reader err */ B_illegal, /* 59 - . illegal */ B_illegal, /* 60 - ) illegal */ B_illegal, /* 61 - [ illegal */ B_illegal, /* 62 - < illegal */ B_illegal /* 63 - Î illegal */ }; /**************************************************************************** * B_BAV * Inputs: * unsigned char d: d-character, ignored * Result: boolean * true to branch * false to not branch * Effect: * tests the overflow indicator, resets it if true ****************************************************************************/ /*ARGSUSED */ boolean B_BAV(unsigned char d) { if(overflow) { /* yes */ overflow = false; return true; } /* yes */ return false; } /**************************************************************************** * B_BC9 * Inputs: * unsigned char d: d-character, ignored * Result: boolean * true to branch * false to not branch * Function: * Tests channel 9 on the printer carriage tape ****************************************************************************/ /*ARGSUSED */ extern boolean C9; boolean B_BC9(unsigned char d) { return C9; } /**************************************************************************** * B_BCV * Inputs: * unsigned char d: d-character, ignored * Result: boolean * true to branch * false to not branch * Function: * Tests channel 12 on the printer carriage tape ****************************************************************************/ /*ARGSUSED */ extern boolean C12; boolean B_BCV(unsigned char d) { return C12; } /**************************************************************************** * B_GT * Inputs: * unsigned char d: d-char, ignored * Result: boolean * true if take branch on B>A, false if not to take branch ****************************************************************************/ /*ARGSUSED */ boolean B_GT(unsigned char d) { return compare_state == logic_BGTA; } /**************************************************************************** * B_LT * Inputs: * unsigned char d: d-char, ignored * Result: boolean * true if take branch on Bindicate.active) { indicator = true; tape->indicate.active = false; if(!tape_transfer_error) { IO_indicator(alert_tape); } } } return(indicator); } /**************************************************************************** * B_ER * Inputs: * unsigned char d: d-character we have encountered * Result: boolean * true if we are to take branch * false if we are not to take branch * Function: * Tests the parity error flags of all drives. (Note the 1401 * Tape Instruction manual A24-3069-2): * * "The BRANCH IF TAPE ERROR instruction must be given after a tape * read or write operation because any tape operation on any tape unit * causes the indicator to turn off." * * As a result, the tape_transfer_error flag is a global. ****************************************************************************/ boolean B_ER(unsigned char d) { boolean indicator; indicator = tape_transfer_error; tape_transfer_error = false; IO_indicator(alert_tape); return(indicator); } /**************************************************************************** * B_perr * Inputs: * unsigned char d: d-character of instruction * Result: boolean * true to branch * false to not branch * Effect: * if the process I/O indicator was on, turn it off ****************************************************************************/ boolean B_perr(unsigned char d) { switch(d) { /* decode */ case 26: /* Ø - printer error */ return IO_indicator(alert_printer); case 42: /* ! - punch error */ return IO_indicator(alert_punch); case 58: /* ? - reader error */ return IO_indicator(alert_reader); } /* decode */ return false; } /**************************************************************************** * B_illegal * Inputs: * unsigned char d: d-char we have encountered * Result: boolean * false, always * Effect: * Initiates a process halt because of an illegal d-character ****************************************************************************/ /*ARGSUSED */ boolean B_illegal(unsigned char d) { bad_d("Branch",d); alert(alert_process); return false; } /**************************************************************************** * B_nop * Inputs: * unsigned char d: d-char of conditional branch * Result: boolean * false, always ****************************************************************************/ /*ARGSUSED */ boolean B_nop(unsigned char d) { return false; } /**************************************************************************** * B_uncond * Inputs: * unsigned char d: d-char of conditional branch (space means * unconditional, which is the only value this will ever see) * Result: boolean * true, always ****************************************************************************/ /*ARGSUSED */ boolean B_uncond(unsigned char d) { return true; } /**************************************************************************** * inst_B * Result: boolean * true if processing should continue * false if processing should halt * Effect: * Executes the unconditional, conditional, or character branch ****************************************************************************/ boolean inst_B() { tell_op(op_A|op_B|op_d); switch(I_cycle) { /* B */ case 1: /* chained */ if(bad_address(B_addr)) return false; switch(single_cycle_state) { /* state decode */ case single_cycle_run: B = memory[B_addr]; if(BA8421(B) == d_char) { /* take branch */ NI_addr = A_addr; B_addr = I_addr; poll(); } /* take branch */ else { /* don't branch */ B_addr--; } /* don't branch */ single_cycle_state = single_cycle_complete; break; case single_cycle_start: B = memory[B_addr]; B_addr--; cycle = cycle_B; single_cycle_state = B_B_f_complete; break; case B_B_f_complete: if(BA8421(B) == d_char) { /* take branch */ NI_addr = A_addr; B_addr = I_addr; poll(); } /* take branch */ single_cycle_state = single_cycle_complete; default: sprintf(diag_buffer,"Illegal microstate %s",single_cycle_decode()); tell(diag_buffer); single_cycle_state = single_cycle_complete; } /* state decode */ tell_new_state("BCE"); break; /* Biii */ case 4: /* one-address */ NI_addr = A_addr; B_addr = I_addr; poll(); single_cycle_state = single_cycle_complete; tell_new_state("B"); break; /* Biiid */ case 5: /* one address + d */ /* Check the condition, reset if necessary */ if(dcodes[d_char] == NULL) { /* missing d-char */ bad_d("No branch dispatch",d_char); alert(alert_process); return false; } /* missing d-char */ if((*dcodes[d_char])(d_char)) { /* take branch */ NI_addr = A_addr; B_addr = I_addr; poll(); } /* take branch */ single_cycle_state = single_cycle_complete; tell_new_state("BIN"); break; /* Biiibbbd */ case 8: /* two-address + d */ if(bad_address(B_addr)) return false; switch(single_cycle_state) { /* state decode */ case single_cycle_run: B = memory[B_addr]; if(BA8421(B) == d_char) { /* take branch */ NI_addr = A_addr; B_addr = I_addr; poll(); } /* take branch */ else { /* don't branch */ B_addr--; } /* don't branch */ single_cycle_state = single_cycle_complete; break; case single_cycle_start: B = memory[B_addr]; A = d_char; /* this may not be right... */ B_addr--; cycle = cycle_B; single_cycle_state = B_B_f_complete; break; case B_B_f_complete: if(BA8421(B) == d_char) { /* take branch */ NI_addr = A_addr; B_addr = I_addr; poll(); } /* take branch */ single_cycle_state = single_cycle_complete; } /* state decode */ /* be sure to reset any indicators as described in 'notes' */ single_cycle_state = single_cycle_complete; tell_new_state("BCE"); break; default: /* Illegal */ illegal_length(); return false; } return true; }