/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 25-Nov-85 | [1.131] Created * 8-Dec-85 | [1.157] Set single_cycle_complete at end of run decode * 25-Jan-86 | [1.327] Check for bad length; note we do not check for 8-char * | device moves * 27-Jan-86 | [1.350] declare single_cycle_decode() * 25-Feb-86 | [1.379] include <> => include "" * 10-Nov-91 | [1.428] converted to Microsoft C 6.0 libraries * 18-Nov-91 | [1.428] memory.h => mem1401.h, avoid ANSI name * 05-Jan-95 | [1.600J] JRJ Implemenent Tape I/O *****************************************************************************/ #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" #include "button.h" #include "tape.h" /* Machine State: */ #define MLCWA_A_complete single_cycle(i_MLCWA,A_complete) #define MLCWA_B_complete single_cycle(i_MLCWA,B_complete) extern char * single_cycle_decode(); /***************************************************************************** 1401 Simulator Load Instruction (Move Left Characters to Wordmark in A-field) Load (Device Address) --------------------- Instruction Format: Mnemonic Op Code A-address B-address d-char -------- ------- --------- --------- ------ LU L %Dn BBB d Function: Device-specific. Cannot be chained. Load (Two Addresses) -------------------- Instruction format Mnemonic Op Code A-address B-address -------- ------- --------- --------- MLCWA L AAA BBB Function: The instruction is commonly used to load data into designated printer or punch output areas of storage, and also to transfer data or instructions from a designated read-in area to another storage area. The data and word mark from the A-field are transferred to the B-field, and all other word marks in the B-field are cleared. Word Marks: The A-field must have a defining word mark, because the A-field word mark stops the operation. Note: If the B-field is larger than the A-field, the B-field word mark is not cleared. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-La B-La Chaining: This instruction can be chained to the preceding operation (if that instruction left usable address-register contents) by supplying only the operation code. Load Characters (One Address) ----------------------------- Instruction format Mnemonic Op Code A-address -------- ------- --------- MLCWA L AAA Function: This format can be used when several A-fields (not necessarily in sequence) are to be loaded sequentially to the B-field. This instruction causes the A-field data and word mark to be moved to the B-field. B-field word marks are cleared, up to the A-field word mark. Word Marks: The A-field word mark stops the operation. Therefore, B-field word marks beyond the left limit of the A-field are not cleared. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-La Bp-La 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_MLCWA * result: boolean * true if instruction succeeded * false if instruction failed * Effect: * Executes load-characters-to-A-field-word-mark instruction ****************************************************************************/ boolean inst_MLCWA() { 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(true)); break; case BCD_W: return(tape_io_write(true)); 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; } } switch(I_cycle) { case 1: /* chained */ case 4: /* one-address */ case 7: /* two-address */ break; default: /* Illegal length */ illegal_length(); return false; } while(cycling) { /* move chars */ if(bad_address(A_addr)) { /* bogus */ cycle = cycle_A; result = false; quit = true; cycling = false; break; } /* bogus */ if(bad_address(B_addr)) { /* bogus */ cycle = cycle_B; result = false; quit = true; cycling = false; break; } /* bogus */ switch(single_cycle_state) { /* state decode */ case single_cycle_run: A = B = memory[B_addr] = memory[A_addr]; quit = WM(B); A_addr--; B_addr--; break; case MLCWA_B_complete: case single_cycle_start: B = memory[A_addr]; A_addr--; cycle = cycle_A; single_cycle_state = MLCWA_A_complete; cycling = false; break; case MLCWA_A_complete: A = B; memory[B_addr] = A; B_addr--; cycle = cycle_B; single_cycle_state = MLCWA_B_complete; quit = WM(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("MLCWA"); return result; }