/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 25-Nov-85 | [1.131] Created * 8-Dec-85 | [1.157] Set single_cycle_complete at end of run decode * 8-Dec-85 | [1.157] Created MLC.c from MLCWA.c * 25-Jan-86 | [1.327] Check for bad length. Note we don't handle device * | move instructions of length 8 yet * 27-Jan-86 | [1.350] declare single_cycle_decode * 25-Feb-86 | [1.379] include <> => include "" * 18-Nov-91 | [1.428] memory.h => mem1401.h, avoid ANSI name * 22-Dec-94 | [1.600J] JRJ add code to identify I/O operations. *****************************************************************************/ #include "stdio.h" #include "btypes.h" #include "mem1401.h" #include "boolean.h" #include "mach.h" #include "machmem.h" #include "diag.h" #include "instr.h" #include "ifetch.h" #include "io.h" #include "alert.h" #include "alerts.h" /* Machine State: */ #define MLC_last (local_microstate+1) #define MLC_A_complete single_cycle(i_MLC,A_complete) #define MLC_B_complete single_cycle(i_MLC,B_complete) #define MLC_A_last single_cycle(i_MLC,MLC_last) extern char * single_cycle_decode(); /***************************************************************************** 1401 Simulator Move Instruction (Move Left Characters to Wordmark in A- or B-field) Move (Device Address) --------------------- Instruction Format: Mnemonic Op Code A-address B-address d-char -------- ------- --------- --------- ------ MU M %Dn BBB d Function: Device-specific. Cannot be chanined. Move (Two Addresses) -------------------- Instruction format Mnemonic Op Code A-address B-address -------- ------- --------- --------- MLC M AAA BBB Function: The data in the A-field is moved to the B-field Word Marks: If both fields are the same length, only one of the fields must have a defining word mark. The first word mark encountered stops the operantion. If the word mark is sensed in the A-field, the machine takes one more B-cycle to move the high-order character from A to B. At the end of the operation, the A-address register and the B-address register contain the address of the storage locations immediately to the left of the A- and B=fields processed by the instruction. The data at the A-address is unaffected by the move operation. Word marks in both fields are undisturbed. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-Lw B-Lw Chaining: This instruction can be chained to the preceding operation (if that instruction left usable address-register contents) by supplying only the operation code. Move Characters (One Address) ----------------------------- Instruction format Mnemonic Op Code A-address -------- ------- --------- MLC M AAA Function: This format can be used when several A-fields (not necessarily in sequence) are to be loaded sequentially to the B-field. It saves program storage space and time, because the B-address is automatically taken from the B-address register and does not have to be written or interpreted as part of the instruction. Word Marks: A word mark is required over the high-order position of the A- or B-field. The first word mark encountered stops the move operation. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-Lw Bp-Lw Chaining: This instruction can be chained to the preceding operation (if that instruction left usable address-register contents) by supplying only the operation code. *****************************************************************************/ /**************************************************************************** * inst_MLC * result: boolean * true if instruction succeeded * false if instruction failed * Effect: * Executes move-characters-to-A-or-B-field-word-mark instruction ****************************************************************************/ boolean inst_MLC() { boolean quit; boolean result; boolean cycling; tell_op(op_A|op_B); result = true; cycling = true; quit = false; /* If this is an I/O instruction, then the length must be 8. Otherwise, it is a regular move instruction, which can be chained. */ if(io_index_inhibit) { if(I_cycle != 8) { illegal_length(); return false; } } else { switch(I_cycle) { case 1: /* chained */ case 4: /* one-address */ case 7: /* two-address */ break; default: /* Illegal length */ illegal_length(); return false; } } if(io_index_inhibit) { switch(io_device) { case BCD_U: switch(d_char) { case BCD_R: return(tape_io_read(false)); break; case BCD_W: return(tape_io_write(false)); break; default: tell("Invalid Tape I/O d character.\n"); alert(alert_process); return(false); } default: tell("Invalid I/O Device.\n"); alert(alert_ramac); break; } } while(cycling) { /* move chars */ if(bad_address(A_addr)) { /* bogus */ cycle = cycle_A; result = false; break; } /* bogus */ if(bad_address(B_addr)) { /* bogus */ cycle = cycle_B; result = false; break; } /* bogus */ switch(single_cycle_state) { /* state decode */ case single_cycle_run: memory[B_addr] = B = BA8421(A = memory[A_addr]) | WM(memory[B_addr]); quit = WM(memory[A_addr]) || WM(memory[B_addr]); A_addr--; B_addr--; break; case MLC_B_complete: case single_cycle_start: B = memory[A_addr]; single_cycle_state = (WM(A) ? MLC_A_last : MLC_A_complete); A_addr--; cycle = cycle_A; cycling = false; break; case MLC_A_complete: A = B; memory[B_addr] = BA8421(B) | WM(memory[B_addr]); if(WM(memory[B_addr])) { /* stop */ quit = true; } /* stop */ else { /* continue */ single_cycle_state = MLC_B_complete; } /* continue */ B_addr--; cycle = cycle_B; cycling = false; break; case MLC_A_last: A = B; memory[B_addr] = BA8421(B) | WM(memory[B_addr]); quit = true; B_addr--; cycle = cycle_B; cycling = false; break; default: sprintf(diag_buffer,"Illegal microstate %s",single_cycle_decode()); tell(diag_buffer); result = false; cycling = false; break; } /* state decode */ if(quit) { single_cycle_state = single_cycle_complete; break; } } /* move chars */ tell_new_state("MLC"); return result; }