/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 15-Dec-85 | [1.212] Created * 19-Dec-85 | [1.216] Added debug_ALU mode and check mouse button for abort * 19-Dec-85 | [1.217] If state is unknown, kill instruction * 19-Dec-85 | [1.218] Compute sign bits * 20-Dec-85 | [1.224] Print out address regs in tell_add_state * 20-Dec-85 | [1.230] Do not add overflow into h/o zones if doing complement * | add * 24-Dec-85 | [1.236] Add ALU pipe printout * 26-Dec-85 | [1.237] Use magnitudes instead of carry detect for sign * | determination; maintain magnitude computation during add * 28-Dec-85 | [1.267] Changed state names to more meaningful names. Fixed * | bugs in bogus address detect register cycle setting. Removed * | some dead code * 28-Dec-85 | [1.268] Compare BtoA data after normalization from BCD * 28-Dec-85 | [1.269] Initialize debug_ALU false, set_ALU procedure plus * | new diagnostic button enables it * 24-Jan-86 | [1.314] check_left_mouse_button => check_mouse_halt * 27-Jan-86 | [1.350] Fixed too-many-arguments-to-ALU(...) * 25-Feb-86 | [1.377] Store proper cycle information so single step display * | works properly * 25-Feb-86 | [1.379] include <> => include "" * 31-Jul-86 | [1.405] Made all chars unsigned * 6-Aug-86 | [1.410] Removed 'else' in signbits to defeat stupid compiler * | type check * 6-Aug-86 | [1.410] Added NOTREACHED comments * 6-Aug-86 | [1.410] Args to faddmode, signbits now unsigned char * 10-Nov-91 | [1.428] converted to Microsoft C 6.0 * 18-Nov-91 | [1.428] memory.h => mem1401.h, avoid ANSI name *****************************************************************************/ /***************************************************************************** 1401 Emulator Arithmetic Module This module implements the 1401 arithmetic instructions, A, S, ZA, ZS. Notes: 1. Sign control: If a recomplement cycle is taken, the sign of the B- (result) field is changed and the result is stored in true form. 2. Zone bits: If the fields to be added contain zone bits in other than the high-order position of the B-field and the sign positions of both fields, only the digits are used in a true-add operation. B-field zone bits are removed except for the units and high-order positions in a true-add operation. If a complement add takes place, zone bits are removed from all but the units positions of the B-field. 3. Overflow indication: If an overflow occurs during a true-add operation the overflow indicator is set ON, and the overflow indications are stored over the high-order digit of the B-field. When the A-field exceeds, or is equal to, the B-field length, and the A-field that corresponds to the high-order B-field position contains a zone bit, this zone bit is added to any zone bits present in the high-order B-field position. Condition Result first overflow A-bit second overflow B-bit third overflow A- and B-bits fourth overflow no A- or B-bits For subsequent overflows repeat conditions 1 thru 4. Overflow indication does not occur for a 1-position field. Sign indication: Sign BCD Zones Card code ---- --------- --------- Plus none no zone Plus A-,B-bits 12-zone Minus B-bit 11-zone Plus A-bit 0-zone Result sign given input signs, operation, and magnitude relations ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÑÍÍÍÑÍÍÍÑÍÍÍËÍÍÍÑÍÍÍÑÍÍÍÑÍÍÍËÍÍÍÑÍÍÍÑÍÍÍÑÍÍÍËÍÍÍÑÍÍÍÑÍÍÍÑÍÍÍ» ºA-sign ³ ³ ³ ³ º A ³ A ³ A ³ A º B ³ B ³ B ³ B º AB³ AB³ AB³ ABº ºB-sign ³ ³ A ³ B ³ ABº ³ A ³ B ³ ABº ³ A ³ B ³ ABº ³ A ³ B ³ ABº ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍØÍÍÍØÍÍÍØÍÍÍÎÍÍÍØÍÍÍØÍÍÍØÍÍÍÎÍÍÍØÍÍÍØÍÍÍØÍÍÍÎÍÍÍØÍÍÍØÍÍÍØÍÍ͹ ºA B=A ³ ³ A ³ B ³ ABº ³ A ³ B ³ ABº AB³ AB³ B ³ ABº ³ A ³ B ³ ABº ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍØÍÍÍØÍÍÍØÍÍÍÎÍÍÍØÍÍÍØÍÍÍØÍÍÍÎÍÍÍØÍÍÍØÍÍÍØÍÍÍÎÍÍÍØÍÍÍØÍÍÍØÍÍ͹ ºS B=A ³ AB³ AB³ B ³ ABº AB³ AB³ B ³ ABº ³ A ³ B ³ ABº AB³ AB³ B ³ ABº ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÏÍÍÍÏÍÍÍÏÍÍÍÊÍÍÍÏÍÍÍÏÍÍÍÏÍÍÍÊÍÍÍÏÍÍÍÏÍÍÍÏÍÍÍÊÍÍÍÏÍÍÍÏÍÍÍÏÍÍͼ Types of Add Cycles and Sign of Result ÉÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍ» º Type of ³ A-fld ³ B-fld ³ Type of ³ Result º º Oper. ³ sign ³ sign ³ Add ³ sign º ÌÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍ͹ º ³ ³ + ³ true ³ + º º ³ + ÃÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄĶ º ³ ³ - ³ compl ³ M º º Add ÃÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄĶ º ³ ³ + ³ compl ³ M º º ³ - ÃÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄĶ º ³ ³ - ³ true ³ - º ÌÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍ͹ º ³ ³ + ³ compl ³ M º º ³ + ÃÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄĶ º ³ ³ - ³ true ³ - º º Sub ÃÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄĶ º ³ ³ + ³ true ³ + º º ³ - ÃÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄĶ º ³ ³ - ³ compl ³ M º ÈÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍͼ M = sign of field with larger magnitude *****************************************************************************/ /***************************************************************************** single_cycle_run single_cycle_start ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º fetch A º º set a-sign º º set a-done º º Assume A=B º º A-addr-- º ÈÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍͼ º  A_init_B_fetch ÉÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º fetch B º º save B_addr for recomp. º º set b-sign º º set complement mode º º set carry º ÈÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ º  A_init_add ÉÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º add (l/o digits) º º compute A:B º ÈÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍͼ º º  A_init_store_B ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º determine last cycle º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ º last cycle: º ~last cycle º º compute sign º compute sign º º store data º store data º º B_addr-- º B_addr-- º ÈÍÍÍÍËÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍËÍÍÍÍÍÍÍͼ º º º º ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º   A_A_fetch º º ÉÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍ» º º º is A-field done? º º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ º º º a-done º ~a-done º º º º fetch '0' º fetch A º º º º º save zonesº º º º º a-done? º º º º º A_addr-- º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍͼ º º º º º  A_B_fetch º º ÉÍÍÍÍÊÍÍÍÍÍÍÍ» º º º fetch B º º º º save zones º º º º b-done? º º º ÈÍÍÍÍËÍÍÍÍÍÍͼ º º º º º  A_add º º ÉÍÍÍÊÍÍÍ» º º º add º º º º A:B º º º ÈÍÍÍËÍÍͼ º º º º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º   A_add_cycle_completeº º ÉÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º determinte last cycle º º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ º º º last cycle: º ~last cycle: º º º º compute h/o zones º º º º º store data º store data º º º º B_addr-- º B_addr-- º º º ÈÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍͼ º º º º º ÈÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍͼ ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ º  A_B_field_complete ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º decide recomplement º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ º ~recomp º recomp º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍ͹ º º carry = 1 º carry = 0 º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍ͹ º º ºreset B-addr º º º compute & º º º º store sign º º ÈÍÍÍÍÍÍËÍÍÍÍÍÍÊÍÍÍÍÍÍËÍÍÍÍÍÍÊÍÍËÍÍÍÍÍÍÍÍÍͼ º º º º º  A_recomp_init_f º º ÉÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍ» º º º fetch B-data º º º º complement it º º º º compute sign º º º ÈÍÍÍÍÍËÍÍÍÍÍÍÍÍÍͼ º º º º º  A_recomp_init_s º º ÉÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍ» º º º store B-data º º º º B_addr-- º º º º b-done? º º º º yes no º º º ÈÍËÍÍÍÍÍÍÍÍËÍÍÍÍͼ º º º º º º º º ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º   A_recomp_fetch º º º º ÉÍÍÍÍÍÊÍÍÍÍÊÍÍÍÍÍ» º º º º º fetch B-data º º º º º º complement it º º º º º ÈÍÍÍÍÍËÍÍÍÍÍÍÍÍÍͼ º º º º º º º º º  A_recomp_store º º º º ÉÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍ» º º º º º store B-data º º º º º º B_addr-- º º º º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ º º º º º b-done? º º º º º ÌÍÍÍÍÍÍÍÍËÍÍÍÍÍÍ͹ º º º º º yes º no º º º º º ÈÍÍÍËÍÍÍÍÊÍÍÍËÍÍͼ º º   º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍËÍÊÍÍÍÍͼ ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ º  single_cycle_complete ÉÍÍÍÊÍÍÍ» º DONE! º ÈÍÍÍÍÍÍͼ *****************************************************************************/ #include "stdio.h" #include "boolean.h" #include "btypes.h" #include "diag.h" #include "instr.h" #include "mach.h" #include "mem1401.h" #include "logic.h" #include "bcd.h" #include "arith.h" #include "kb.h" #include "scan.h" /* State retained across microcycles */ unsigned char a_sign; /* zone bits of A-field low order position */ unsigned char b_sign; /* zone bits of B-field low order position */ unsigned char b_ovf; /* zone bits of B-field high order position */ unsigned char a_ovf; /* zone bits of A-field high order (presumed) position (ignored if not b_done) */ boolean complement; /* true if complement add required */ int carry; /* 0 or 1; 0 if no carry, 1 if carry */ int a_done; /* A-field terminated with WM */ int b_done; /* B-field terminated with WM */ int init_B_addr; /* Initial B-address */ boolean single; /* Are we in single-cycle mode? */ boolean debug_ALU = false; /* debug mode */ int last_state; /* last state we were in for debug printout */ int BtoA; /* comparison of B to A */ #define A_base (local_microstate+1) #define A_init_B_fetch single_cycle(i_A,A_base+1) #define A_init_add single_cycle(i_A,A_base+2) #define A_init_store_B single_cycle(i_A,A_base+3) #define A_B_field_complete single_cycle(i_A,A_base+4) #define A_recomp_init_f single_cycle(i_A,A_base+5) #define A_recomp_init_s single_cycle(i_A,A_base+6) #define A_recomp_fetch single_cycle(i_A,A_base+7) #define A_recomp_store single_cycle(i_A,A_base+8) #define A_A_fetch single_cycle(i_A,A_base+9) #define A_B_fetch single_cycle(i_A,A_base+10) #define A_add single_cycle(i_A,A_base+11) #define A_add_cycle_complete single_cycle(i_A,A_base+12) char * arith_state_decode(short state); static void tell_add_state(boolean op); /**************************************************************************** * signbits * Inputs: * unsigned char asign: A-sign bit configuration * unsigned char bsign: B-sign bit configuration * boolean op: true for add, false for subtract * int BtoA: Comparison of B to A, gives relative magnitude: * logic_BEQA * logic_BGTA * logic_BLTA * Result: int * Sign bits of result, based on tables as specified in 1401 manual * Notes: * The determination of the relative magnitudes also determines the * need to recomplement the result; thus during the recomplement cycle * we call for the sign bit given the magnitude considerations. ****************************************************************************/ int addsign[4][4][2] = { /* Bsign 0 A B AB +----------------+----------------+----------------+-----------------+ A-sign | B=A | B=A | B=A | B=A | 0 */{{0 ,0 },{A_bits,A_bits} ,{BA_bits,B_bits},{BA_bits,BA_bits}}, /* A */{{0 ,0 },{A_bits,A_bits} ,{BA_bits,B_bits},{BA_bits,BA_bits}}, /* B */{{B_bits,BA_bits},{B_bits,BA_bits},{B_bits, B_bits},{B_bits ,BA_bits}}, /* AB*/{{0 ,0 },{A_bits,A_bits} ,{BA_bits,B_bits},{BA_bits,BA_bits}} }; int subsign[4][4][2] = { /* Bsign 0 A B AB +---------------+----------------+----------------+------------------+ A-sign | B=A | B=A | B=A | B=A | 0 */{{B_bits,BA_bits},{B_bits,BA_bits},{B_bits ,B_bits},{B_bits ,BA_bits}}, /* A */{{B_bits,BA_bits},{B_bits,BA_bits},{B_bits ,B_bits},{B_bits ,BA_bits}}, /* B */{{0 ,0 },{A_bits,A_bits} ,{BA_bits,B_bits},{BA_bits,BA_bits}}, /* AB*/{{B_bits,BA_bits},{B_bits,BA_bits},{B_bits ,B_bits},{B_bits ,BA_bits}} }; short signbits(unsigned char asign, unsigned char bsign, boolean op, short BtoA) { if(op) return addsign[ZONEBITS_DOWN(asign)][ZONEBITS_DOWN(bsign)][(BtoA == logic_BLTA ? 0 : 1)]; return subsign[ZONEBITS_DOWN(asign)][ZONEBITS_DOWN(bsign)][(BtoA == logic_BLTA ? 0 : 1)]; } /**************************************************************************** * ALU * Inputs: * unsigned char a: A_data * unsigned char b: B_data * Result: unsigned char * Result of adding a to b, with all zone bits stripped ****************************************************************************/ unsigned char ALU(unsigned char a, unsigned char b) { int a_data; int b_data; int result; a_data = NUMBITS(a); b_data = NUMBITS(b); if(a_data == 10) a_data = 0; if(b_data == 10) b_data = 0; if(b_data > a_data) BtoA = logic_BGTA; else if(b_data < a_data) BtoA = logic_BLTA; if(diagnostics_on && debug_ALU) { /* trace ALU */ sprintf(diag_buffer,"ALU stage 1: a_data=%d, b_data=%d",a_data, b_data); tell(diag_buffer); } /* trace ALU */ if(complement) { /* 9s complement */ a_data = 9 - a_data; if(diagnostics_on & debug_ALU) { /* trace ALU */ sprintf(diag_buffer, "ALU stage 2 [post complement]: a_data=%d, b_data=%d", a_data, b_data); tell(diag_buffer); } /* trace ALU */ } /* 9s complement */ result = a_data + b_data + carry; if(diagnostics_on && debug_ALU) { /* trace ALU */ sprintf(diag_buffer,"ALU stage 3 [sum]: %d = %d + %d + %d", result, a_data, b_data, carry); tell(diag_buffer); } /* trace ALU */ if(result > 9) { /* carry */ carry = 1; result -= 10; } /* carry */ else carry = 0; if(diagnostics_on && debug_ALU) { /* trace ALU */ sprintf(diag_buffer,"ALU stage 4 [carry detect]: %d, carry %d", result,carry); tell(diag_buffer); } /* trace ALU */ if(result == 0) result = 10; return (unsigned char) result; } /**************************************************************************** * faddmode * Inputs: * unsigned char a_sign: Zone bits of A-field, in normal position * unsigned char b_sign: Zone bits of B-field, in normal position * boolean add: True if add, false if subtract * Result: boolean * true if true add to be used * false if complement add to be used ****************************************************************************/ #define T true #define C false boolean faddmode_table[4][4][2] = { /* B=none B ='A' B='B' B='AB' */ /* add,sub add,sub add,sub add,sub */ /* A-sign none */ { { T,C }, { T,C }, { C,T }, { T,C } }, /* A-sign 'A' */ { { T,C }, { T,C }, { C,T }, { T,C } }, /* A-sign 'B' */ { { C,T }, { C,T }, { T,C }, { C,T } }, /* A-sign 'AB' */ { { T,C }, { T,C }, { C,T }, { T,C } } }; boolean faddmode(unsigned char a_sign, unsigned char b_sign, boolean add) { return faddmode_table[ZONEBITS_DOWN(a_sign)][ZONEBITS_DOWN(b_sign)] [(add ? 0 : 1)]; } /**************************************************************************** * arith * Inputs: * boolean op: true is add, false is subtract * Result: boolean * true if OK * false if error * Effect: * Algebraically adds or substracts the A-field from the B-field * according to the rules given in the introduction above ****************************************************************************/ boolean arith(boolean op) { boolean cycling; boolean result = true; boolean report; if(single_cycle_state == single_cycle_start) single = true; else if(single_cycle_state == single_cycle_run) single = false; cycling = true; while(cycling) { /* add fields */ last_state = single_cycle_state; switch(single_cycle_state) { /* state decode */ case single_cycle_start: case single_cycle_run: /* Set up initial conditions */ if(bad_address(A_addr)) { /* bogus */ cycle = cycle_A; result = false; cycling = false; break; } /* bogus */ B = memory[A_addr]; a_sign = ZONEBITS(B); a_done = WM(B); b_done = false; BtoA = logic_BEQA; A_addr--; single_cycle_state = A_init_B_fetch; cycle = cycle_A; break; case A_init_B_fetch: if(bad_address(B_addr)) { /* bogus */ cycle = cycle_B; result = false; cycling = false; break; } /* bogus */ A = B; B = memory[B_addr]; init_B_addr = B_addr; b_sign = ZONEBITS(B); b_done = WM(B); b_ovf = 0; complement = !faddmode(a_sign,b_sign,op); if(complement) carry = 1; else carry = 0; single_cycle_state = A_init_add; cycle = cycle_B; break; case A_init_add: L = ALU(A,B); /* Compute sign bits */ L |= signbits(a_sign,b_sign,op,BtoA); single_cycle_state = A_init_store_B; break; case A_A_fetch: if(a_done) { /* short A-field */ B = 10; /* BCD '0' */ a_ovf = 0; } /* short A-field */ else { /* still fetching A */ if(bad_address(A_addr)) { /* bogus */ cycle = cycle_A; result = false; cycling = false; break; } /* bogus */ B = memory[A_addr]; a_ovf = ZONEBITS(B); a_done = WM(B); A_addr--; } /* still fetching A */ single_cycle_state = A_B_fetch; cycle = cycle_A; break; case A_B_fetch: if(bad_address(B_addr)) { /* bogus */ cycle = cycle_B; result = false; cycling = false; break; } /* bogus */ A = B; B = memory[B_addr]; b_ovf = ZONEBITS(B); b_done = WM(B); cycle = cycle_B; single_cycle_state = A_add; break; case A_add: L = ALU(A,B); /* Compute sign bits */ single_cycle_state = A_add_cycle_complete; break; case A_add_cycle_complete: if(b_done) { /* compute overflow bits */ b_ovf = ZONEBITS(b_ovf + a_ovf); if(!complement && carry) b_ovf = ZONEBITS(b_ovf+A_bits); } /* compute overflow bits */ else { /* no overflow bits */ b_ovf = 0; } /* no overflow bits */ memory[B_addr] = L | b_done | b_ovf; single_cycle_state = (b_done ? A_B_field_complete : A_A_fetch); B_addr--; cycle = cycle_B; break; case A_init_store_B: memory[B_addr] = L | b_done; single_cycle_state = (b_done ? A_B_field_complete : A_A_fetch); B_addr--; cycle = cycle_B; break; case A_B_field_complete: /* recomplement? */ if(complement) { /* need recomplement? */ /* If there was a carry, no recomplement is necessary; if there was no carry, we need to recomplement the result 1401 Sys Ref Man pp B-2..B-3, figs B-3, B4, B-5 */ if(carry == 1) { /* done */ int t; single_cycle_state = single_cycle_complete; /* compute the result sign */ t = memory[init_B_addr]; t = NUMBITS(t) | WM(t); t |= signbits(a_sign,b_sign,op,BtoA); memory[init_B_addr] = t; break; } /* done */ else { /* need recomplement */ single_cycle_state = A_recomp_init_f; B_addr = init_B_addr; } /* need recomplement */ } /* need recomplement? */ else { /* set overflow flag */ single_cycle_state = single_cycle_complete; if(carry != 0) overflow = true; } /* set overflow flag */ cycle = cycle_B; break; case A_recomp_init_f: /* We don't need to check address because we would have failed earlier on bad address */ B = memory[B_addr]; carry = 1; /* force carry */ L = ALU(B,(unsigned char) 0); L = L | signbits(a_sign,b_sign,op,BtoA); single_cycle_state = A_recomp_init_s; cycle = cycle_B; break; case A_recomp_init_s: b_done = WM(memory[B_addr]); memory[B_addr] = L | b_done; single_cycle_state = (b_done ? single_cycle_complete : A_recomp_fetch); B_addr--; if(single_cycle_state == single_cycle_complete) cycling = false; cycle = cycle_B; break; case A_recomp_fetch: B = memory[B_addr]; carry = 0; /* force carry off */ L = ALU(B,(unsigned char) 0); b_done = WM(B); single_cycle_state = A_recomp_store; cycle = cycle_B; break; case A_recomp_store: memory[B_addr] = L | b_done; if(b_done) single_cycle_state = single_cycle_complete; else single_cycle_state = A_recomp_fetch; B_addr--; cycle = cycle_B; break; default: /* bogus */ tell("Bad add state"); cycling = false; result = false; break; } /* state decode */ if(single_cycle_state==single_cycle_complete) cycling = false; report = diagnostics_on && (single || single_cycle_state == single_cycle_complete); if(diagnostics_on && !report && debug_ALU) { /* debugging */ tell_add_state(op); if(check_mouse_halt()) break; } /* debugging */ if(single) break; } /* add fields */ if(report) tell_add_state(op); return result; } /**************************************************************************** * tell_add_state * Inputs: * boolean op: true for add, false for subtract * Effect: * Tells state of ALU to diagnostic file ****************************************************************************/ static void tell_add_state(boolean op) { char * p = diag_buffer; p += sprintf(p,"%s [%s]=>%s", (op ? "ADD" : "SUB"), arith_state_decode(last_state), arith_state_decode(single_cycle_state)); p += sprintf(p,", A=%c, B=%c, L=%c", bcd_to_ascii(A), bcd_to_ascii(B), bcd_to_ascii(L)); p += sprintf(p,", A_addr=%d, B_addr=%d", A_addr, B_addr); if(a_done) p += sprintf(p,", A done"); if(b_done) p += sprintf(p,", B done"); p += sprintf(p,", Asign=%c, Bsign=%c, Aovf=%c, Bovf=%c", bcd_to_ascii(a_sign), bcd_to_ascii(b_sign), bcd_to_ascii(a_ovf), bcd_to_ascii(b_ovf)); if(complement) p += sprintf(p,", comp"); if(carry != 0) p += sprintf(p,", carry"); p += sprintf(p, ", %s",logic_state(BtoA)); tell(diag_buffer); } /**************************************************************************** * arith_state_decode * Inputs: * int state: State to decode * Result: char * * printable state string ****************************************************************************/ char * arith_state_decode(short state) { switch(state) { /* decode */ case single_cycle_run: return "run"; case single_cycle_start: return "start"; case single_cycle_complete: return "complete"; case A_init_B_fetch: return "init_B_fetch"; case A_init_add: return "init_add"; case A_init_store_B: return "init_store_B"; case A_B_field_complete: return "B_field_complete"; case A_recomp_init_f: return "recomp_init_f"; case A_recomp_init_s: return "recomp_init_s"; case A_recomp_fetch: return "recomp_fetch"; case A_A_fetch: return "A_fetch"; case A_B_fetch: return "B_fetch"; case A_add: return "add"; case A_add_cycle_complete: return "add_cycle_complete"; default: return "?"; } /* decode */ /*NOTREACHED */ return NULL; } /**************************************************************************** * set_ALU_trace * Inputs: * boolean set: Value to set trace to * Effect: * Sets the debug_ALU flag ****************************************************************************/ void set_ALU_trace(boolean set) { debug_ALU = set; }