/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 29-Dec-85 | [1.270] Created * 25-Jan-86 | [1.327] Check for illegal length * 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 *****************************************************************************/ #include "mem1401.h" #include "btypes.h" #include "boolean.h" #include "mach.h" #include "diag.h" #include "instr.h" #include "ifetch.h" #define MA_fetch_A_units single_cycle(i_MA,local_microstate+1) #define MA_fetch_B_units single_cycle(i_MA,local_microstate+2) #define MA_store_B_units single_cycle(i_MA,local_microstate+3) #define MA_fetch_A_tens single_cycle(i_MA,local_microstate+4) #define MA_fetch_B_tens single_cycle(i_MA,local_microstate+5) #define MA_store_B_tens single_cycle(i_MA,local_microstate+6) #define MA_fetch_A_hundreds single_cycle(i_MA,local_microstate+7) #define MA_fetch_B_hundreds single_cycle(i_MA,local_microstate+8) #define MA_store_B_hundreds single_cycle(i_MA,local_microstate+9) #define MA_fetch_B_units_zones single_cycle(i_MA,local_microstate+10) #define MA_store_B_units_zones single_cycle(i_MA,local_microstate+11) static int carry; /***************************************************************************** 1401 Simulator Modify Address Instruction Modify Address (Two Addresses) ------------------------------ Instruction format Mnemonic Op Code A-address B-address -------- ------- --------- --------- MA # AAA BBB Function: This instructioncauses the 3-character field, specified by the A-address (A-field) to be added to the 3-character field specified by the B-address (B-field). The result is stored in the B-field. The three numerical portions and the zones of the units and hundreds positions of the B-field make up the 3-character result. Word Marks: Word marks are not affected, and are not required to define the A- or B-fields. If word marks are present they are ignored and remain unchanged. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-3 B-1 or B-3 Chaining: This instruction can be chained to the preceding operation (if that instruction left usable address-register contents) by supplying only the operation code. Modify Address (One Address) ---------------------------- Instruction format Mnemonic Op Code A-address -------- ------- --------- MA # AAA Function: This format of the Modify Address instruction causes the 3-character field, specified by the A-address to be added to itself. The result is stored in the A-field. Word Marks: Word marks are not required to define the A-field. If they are present, they are ignored and left undisturbed. Address Registers After Operation: I-Add A-Add B-Add ----- ----- ----- NSI A-3 A-1 or A-3 Chaining: This instruction can be chained to the preceding operation (if that instruction left usable address-register contents) by supplying only the operation code. *****************************************************************************/ /**************************************************************************** * madd * Result: int * result of adding numeric portions of A and B registers * Effect: * carry reflects if there was an overflow ****************************************************************************/ int madd() { int a; int b; a = NUMBITS(A); if(a==10) a = 0; b = NUMBITS(B); if(b==10) b = 0; b += a + carry; if(b>9) { /* carry */ carry = 1; b -= 10; } /* carry */ else { /* no carry */ carry = 0; } /* no carry */ if(b==0) b = 10; return b; } /**************************************************************************** * inst_MA * result: boolean * true if instruction succeeded * false if instruction failed * Effect: * Executes the Modify-Address instruction ****************************************************************************/ boolean inst_MA() { boolean quit; boolean result; boolean cycling; boolean run; int sum; int zone; 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) { /* add addresses */ 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: run = true; single_cycle_state = MA_fetch_A_units; carry = 0; break; case single_cycle_start: run = false; single_cycle_state = MA_fetch_A_units; carry = 0; break; case MA_fetch_A_units: A = B = memory[A_addr]; A_addr--; cycle = cycle_A; cycling = run; single_cycle_state = MA_fetch_B_units; break; case MA_fetch_B_units: B = memory[B_addr]; cycle = cycle_B; cycling = run; single_cycle_state = MA_store_B_units; break; case MA_store_B_units: sum = madd(); sum |= (ZONEBITS(A) + ZONEBITS(B)) & BA_bits; B = sum | WM(B); memory[B_addr] = B; B_addr--; cycle = cycle_B; cycling = run; single_cycle_state = MA_fetch_A_tens; break; case MA_fetch_A_tens: A = B = memory[A_addr]; A_addr--; cycle = cycle_A; cycling = run; single_cycle_state = MA_fetch_B_tens; break; case MA_fetch_B_tens: B = memory[B_addr]; cycle = cycle_B; cycling = run; single_cycle_state = MA_store_B_tens; break; case MA_store_B_tens: sum = madd(); sum |= ZONEBITS(B); B = sum | WM(B); memory[B_addr] = B; B_addr--; cycle = cycle_B; cycling = run; single_cycle_state = MA_fetch_A_hundreds; break; case MA_fetch_A_hundreds: A = B = memory[A_addr]; A_addr--; cycle = cycle_A; cycling = run; single_cycle_state = MA_fetch_B_hundreds; break; case MA_fetch_B_hundreds: B = memory[B_addr]; cycle = cycle_B; cycling = run; single_cycle_state = MA_store_B_hundreds; break; case MA_store_B_hundreds: sum = madd(); zone = (ZONEBITS(A) + ZONEBITS(B) + (carry==0 ? 0 : A_bits)); carry = (zone > BA_bits); sum |= zone & BA_bits; B = sum | WM(B); memory[B_addr] = B; B_addr--; cycle = cycle_B; if(carry) { /* must do units zones */ single_cycle_state = MA_fetch_B_units_zones; cycling = run; } /* must do units zones */ else { /* done */ single_cycle_state = single_cycle_complete; cycling = false; } /* done */ break; case MA_fetch_B_units_zones: B_addr += 3; B = memory[B_addr]; single_cycle_state = MA_store_B_units_zones; cycling = run; cycle = cycle_B; break; case MA_store_B_units_zones: B = ((ZONEBITS(B) + A_bits) & BA_bits) | NUMBITS(B) | WM(B); memory[B_addr] = B; B_addr--; cycling = false; single_cycle_state = single_cycle_complete; break; } /* state decode */ } /* add addresses */ return result; }