private void alu(string _a, string _b, ALUOperation alu_control, bool isUnsigned, out bool zero, out string _result) { UInt32 a = Convert.ToUInt32(_a, 2), b = Convert.ToUInt32(_b, 2), result = 0; switch (alu_control) { case ALUOperation.AND: result = a & b; break; case ALUOperation.OR: result = a | b; break; case ALUOperation.ADD: result = a + b; if (!isUnsigned && (int)a > 0 && (int)b > 0 && ((int)result < (int)a || (int)result < (int)b)) // only signed add may overflow { throw new MIPSAssemblerException("ALU Addition Overflow"); } break; case ALUOperation.XOR: result = a ^ b; break; case ALUOperation.NOR: result = ~(a | b); break; case ALUOperation.SRL: result = a >> Convert.ToByte(_b.Substring(21, 5), 2); break; case ALUOperation.SLL: result = a << Convert.ToByte(_b.Substring(21, 5), 2); break; case ALUOperation.SUB: result = a - b; if (result > a && isUnsigned) // only unsigned sub may overflow { throw new MIPSAssemblerException("ALU Addition Overflow"); } break; case ALUOperation.SLT: result = (UInt32)(a < b ? 1 : 0); break; default: //throw new MIPSAssemblerException("ALU Control error"); result = 0; break; } _result = Convert.ToString(result, 2).PadLeft(32, '0'); zero = (result == 0); return; }
public void init( ) { ALU_Control = ALUOperation.ERROR; DatatoReg = DataToRegSrc.ALURes; RegDst = RegWrite = Jal = ALUSrc_B = false; MemRead = MemtoReg = MemWrite = false; ExtSign = Branch = Jump = false; ALU_Unsigned = false; IsBeq = false; DataWidth = 0; }
public void DoALUOp(int amux, int bmux, ALUOperation op) { #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.AluState, "ALU: Inputs: Amux={0:x5} Bmux={1:x5}", amux, bmux); } #endif // Reset carry flag (arithmetic ops will set it as necessary) // but save the original value for use in addition/subtraction w/carry int lastCarry15 = _registers.Cry ? 1 : 0; _registers.Carry19 = 0; bool carry15 = false; bool arithX = false; bool arithY = false; switch (op) { case ALUOperation.A: _registers.R = amux; break; case ALUOperation.B: _registers.R = bmux; break; case ALUOperation.NotA: _registers.R = ~amux; break; case ALUOperation.NotB: _registers.R = ~bmux; break; case ALUOperation.AandB: _registers.R = amux & bmux; break; case ALUOperation.AandNotB: _registers.R = amux & (~bmux); break; case ALUOperation.AnandB: _registers.R = ~(amux & bmux); break; case ALUOperation.AorB: _registers.R = amux | bmux; break; case ALUOperation.AorNotB: _registers.R = amux | (~bmux); break; case ALUOperation.AnorB: _registers.R = ~(amux | bmux); break; case ALUOperation.AxorB: _registers.R = amux ^ bmux; break; case ALUOperation.AxnorB: _registers.R = (amux & bmux) | ((~amux) & (~bmux)); break; case ALUOperation.AplusB: _registers.R = (amux + bmux); arithY = true; // Check for carry-out from bit 19 _registers.Carry19 = _registers.R > 0xfffff ? 1 : 0; // Check for carry-out from bit 15 carry15 = ((amux & 0xffff) + (bmux & 0xffff) > 0xffff); break; case ALUOperation.AplusBplusCarry: _registers.R = (amux + bmux + lastCarry15); arithY = true; // Check for carry-out from bit 19 _registers.Carry19 = _registers.R > 0xfffff ? 1 : 0; // Check for carry-out from bit 15 carry15 = ((amux & 0xffff) + (bmux & 0xffff) + lastCarry15 > 0xffff); break; case ALUOperation.AminusB: _registers.R = (amux - bmux); arithX = true; _registers.Carry19 = ((amux - bmux) < 0) ? 0 : 1; carry15 = ((amux & 0xffff) - (bmux & 0xffff) >= 0); break; case ALUOperation.AminusBminusCarry: _registers.R = (amux - bmux - (~lastCarry15 & 0x1)); arithX = true; _registers.Carry19 = ((amux - bmux - (~lastCarry15 & 0x1)) < 0) ? 0 : 1; carry15 = ((amux & 0xffff) - (bmux & 0xffff) - (~lastCarry15 & 0x1) >= 0); break; default: throw new UnimplementedInstructionException(String.Format("Unhandled ALU operation {0:x1}", op)); } // Clip the result to 20 bits _registers.R = _registers.R & 0xfffff; // Inputs to the condition code PAL, used to build an index into the PAL array. bool r15 = (_registers.R & 0x8000) == 0; bool LAeqB = (_registers.R & 0xffff) != 0; bool Lb15 = (bmux & 0x8000) != 0; bool La15 = (amux & 0x8000) != 0; // Set flags that don't require heavy lifting _registers.Cry = carry15; _registers.Neq = LAeqB; _registers.Eql = !LAeqB; // Look up precomputed ALU PAL results int index = (r15 ? 0x1 : 0) | (La15 ? 0x2 : 0) | (Lb15 ? 0x4 : 0) | (LAeqB ? 0x8 : 0) | (arithX ? 0x10 : 0) | (arithY ? 0x20 : 0); // TODO: could make this faster by having an unsafe array int flags = _palFlags[index]; // Set flags based on the returned table value _registers.Ovf = (flags & 0x1) != 0; _registers.Leq = (flags & 0x2) != 0; _registers.Lss = (flags & 0x4) != 0; _registers.Geq = (flags & 0x8) != 0; _registers.Gtr = (flags & 0x10) != 0; #if TRACING_ENABLED if (Trace.TraceOn) { Trace.Log(LogType.AluState, "ALU: Result: {0}", Registers); } #endif }