/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 27-Dec-85 | [1.242] Created * 25-Jan-86 | [1.327] Check for illegal length * 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 *****************************************************************************/ #include "stdio.h" #include "mem1401.h" #include "btypes.h" #include "boolean.h" #include "mach.h" #include "diag.h" #include "instr.h" #include "ifetch.h" extern char * single_cycle_decode(); /***************************************************************************** 1401 Simulator Zero and Add Instruction Zero and Add (Two Addresses) ---------------------------- Instruction format Mnemonic Op Code A-address B-address -------- ------- --------- --------- ZA ? AAA BBB Function: The data in the A-field is added to a zeroed B-field. The result is stored in the B-field. Technically, this is accomplished by moving the A-field to the B-field. The high order positions of the B-field are set to zero if the B-field is longer than the A-field. The data from the A-field moves directly from the A-register to storage. Zone bits are stripped from all positions except the units position. Blanks in the A-field are stored as blanks in the B-field. Word Marks: The B-field must have a defining word mark, because it is this word mark which actually stops the add operation. The A-field must have a word mark only if it is shorter than the B-field. In this case, the transmission of data from the A-field stops after the A-field word mark is sensed. Zeros are then inserted in the A-register until the B-field word mark is sensed. If the A-field is longer than the B-field, the high-order positions of the A-field that exceed the limits imposed by the B-field are not processed. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-Lw B-Lb Chaining: This instruction can be chained to the preceding operation (if that instruction left usable address-register contents) by supplying only the operation code. Zero-and-Add (One Address) -------------------------- Instruction format Mnemonic Op Code A-address -------- ------- --------- ZA ? AAA Function: This format of the zero and add instruction is used to strip the A-field of all zone bits, except in the units position (sign). The A-field sign is retained, and if it si plus, the bit configuration might change. If the A-field plus-sign bit configuration is not an AB bit configuration, it is changed to an AB bit configuration. Word marks: The A-field must have a word mark in the high-order position. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-La A-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. *****************************************************************************/ static boolean a_done; #define ZA_A_f_complete single_cycle(i_ZA,A_f_complete) #define ZA_B_s_complete single_cycle(i_ZA,B_s_complete) /**************************************************************************** * inst_ZA * result: boolean * true if instruction succeeded * false if instruction failed * Effect: * Executes zero-and-add instruction ****************************************************************************/ boolean inst_ZA() { boolean quit; boolean result; boolean cycling; boolean run; tell_op(op_A|op_B); result = true; cycling = true; quit = false; 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; 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: B = memory[A_addr]; run = true; A = B; if(ZONEBITS(B) != B_bits) A |= BA_bits; A = BA8421(A); A_addr--; a_done = WM(B); /* FALLS THRU */ case ZA_A_f_complete: /* Store the value we have just fetched */ memory[B_addr] = A | WM(memory[B_addr]); quit = WM(memory[B_addr]); B_addr--; cycling = run; single_cycle_state = ZA_B_s_complete; break; case single_cycle_start: B = memory[A_addr]; run = false; A = B; if(ZONEBITS(B) != B_bits) A |= BA_bits; A = BA8421(A); single_cycle_state = ZA_A_f_complete; A_addr--; a_done = WM(B); cycle = cycle_A; cycling = run; break; case ZA_B_s_complete: if(a_done) B = 10; /* BCD 0 */ else { /* fetch A */ B = memory[A_addr]; A_addr--; a_done = WM(B); } /* fetch A */ A = NUMBITS(B); cycle = cycle_A; cycling = run; single_cycle_state = ZA_A_f_complete; 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("ZA"); return result; }