示例#1
0
        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;
        }
示例#2
0
            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;
            }
示例#3
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
        }