Exemplo n.º 1
0
        public void execute()
        {
            /*          - Execute:
             *                      0- If it is jump or beq ... ---> Set PC to addres in jump...
             *                      1- If Instruction is Interrupt (here only syscall)... well interrupt the process.
             *                      2- If Memory Access Instruction:
             *                          - Place Address in Memory Address Register (MAR);
             *                          - Then Access Memory (either read data from MDR and place in Mem, or read from Mem and place in MDR)
             *                      3- Else excecute (on registers);
             *
             */
            // 1- Check if its jump
            if (instruction.format == 2)
            {
                //Decode Address;
                string address = IR.Substring(6);

                string pc_string = Convert.ToString(PC, 2);
                extendbin(ref pc_string, 32);
                //Put 00 in the end and the 4 most significant bits from pc in the front
                address = pc_string.Substring(0, 4) + address + "00";  //Absolute Address

                //Now check wether it's just jump or jump and link
                if (instruction.mnemonic == "jal")
                {
                    //set register RA = old PC +4
                    Register.Registers.ElementAt <Register>(31).write(PC);  //JAL sets the RA to next instruction after JAL.
                }
                //Add that to the PC
                int add = Convert.ToInt32(address, 2);
                PC = add;
                //Increment Clock

                Excecuted.Invoke();
            }
            // 1- iformat
            else if (instruction.format == 1)
            {
                //Check if it's BRANCH
                switch (instruction.mnemonic)
                {
                case "beq":
                    //Check for Condition.
                    string rs     = IR.Substring(6, 5);
                    string rt     = IR.Substring(11, 5);
                    int    rs_val = Register.GetValfromBIN(rs);
                    int    rt_val = Register.GetValfromBIN(rt);

                    if (rt_val == rs_val)
                    {
                        //Since its a branch, calculate the address like this
                        //add the two zeros, then sign extend, then turn to signed int
                        //then add it to PC+1;
                        //... first load the 16 bit address :P
                        string address = IR.Substring(16);
                        address = address + "00";
                        signExtend(ref address, 32);
                        int adrs = Convert.ToInt32(address, 2);
                        PC = PC + adrs;      //Calculate new PC;

                        Excecuted.Invoke();
                    }
                    //ELSE DO NOTHING, PC ALREADY INCREMENTED BY FETCH!
                    break;

                case "bne":
                    rs     = IR.Substring(6, 5);
                    rt     = IR.Substring(11, 5);
                    rs_val = Register.GetValfromBIN(rs);
                    rt_val = Register.GetValfromBIN(rt);

                    if (rt_val != rs_val)
                    {
                        //Since its a branch, calculate the address like this
                        //add the two zeros, then sign extend, then turn to signed int
                        //then add it to PC+1;
                        //... first load the 16 bit address :P
                        string address = IR.Substring(16);
                        address = address + "00";
                        signExtend(ref address, 32);
                        int adrs = Convert.ToInt32(address, 2);
                        PC = PC + adrs;      //Calculate new PC;

                        Excecuted.Invoke();
                    }
                    break;

                case "addi":
                    //Get the registers, do the operation.
                    //Remmber this has overflow!
                    rs     = IR.Substring(6, 5);
                    rt     = IR.Substring(11, 5);
                    rs_val = Register.GetValfromBIN(rs);
                    string imm = IR.Substring(16);
                    signExtend(ref imm, 32);

                    //Good boy, now add and pc+1
                    int imm_sint = Convert.ToInt32(imm, 2);
                    int val      = rs_val + imm_sint;

                    //Before writing to register, lets check for overflow.
                    //By translating to bitstring and seeing the size, if more than 32 bits.. overflow
                    if (overflow(val, 32))
                    {
                        OverFlow.Invoke();
                        Terminate_Error.Invoke("Overflow from instruction in PC: " + PC.ToString() + " has been detected");
                    }
                    else
                    {
                        //No Overflow, so far so good, replace value in rt by val
                        Register.Registers.ElementAt <Register>(Convert.ToInt32(rt, 2)).write(val);

                        Excecuted.Invoke();
                    }

                    break;

                case "addiu":
                    //No Overflow;
                    rs     = IR.Substring(6, 5);
                    rt     = IR.Substring(11, 5);
                    rs_val = Register.GetValfromBIN(rs);
                    imm    = IR.Substring(16);
                    signExtend(ref imm, 32);

                    //Good boy, now add and pc+1
                    imm_sint = Convert.ToInt32(imm, 2);
                    val      = rs_val + imm_sint;
                    Register.Registers.ElementAt <Register>(Convert.ToInt32(rt, 2)).write(val);

                    Excecuted.Invoke();
                    break;

                //Now the load store instructions
                case "lb":
                    //              CANNOT TEST MARS DUMP BEFORE ADDING LUI AND SOME OTHER STUFF
                    //$t = MEM[$s + offset];
                    //first calculate the address to load from
                    rs     = IR.Substring(6, 5);
                    rt     = IR.Substring(11, 5);
                    rs_val = Register.GetValfromBIN(rs);
                    imm    = IR.Substring(16);
                    signExtend(ref imm, 32);
                    imm_sint = Convert.ToInt32(imm, 2);

                    ulong addres  = (ulong)rs_val + (ulong)imm_sint;
                    byte  value_b = Mem.loadByte(addres);
                    Register.Registers.ElementAt <Register>(Convert.ToInt32(rt, 2)).write(value_b);
                    break;

                case "sb":
                    rs     = IR.Substring(6, 5);
                    rt     = IR.Substring(11, 5);
                    rs_val = Register.GetValfromBIN(rs);
                    rt_val = Register.GetValfromBIN(rt);
                    string rt_vals = Convert.ToString(rt_val, 2);
                    imm = IR.Substring(16);
                    signExtend(ref imm, 32);
                    imm_sint = Convert.ToInt32(imm, 2);

                    addres = (ulong)rs_val + (ulong)imm_sint;
                    //Since the way i design the memory here is to access a stream of bytes
                    //I need to harnes a byte from my current int
                    byte rt_b = Convert.ToByte(rt_vals.Substring(27));
                    Mem.storeByte(addres, rt_b);
                    break;

                case "andi":
                    rs     = IR.Substring(6, 5);
                    rt     = IR.Substring(11, 5);
                    rs_val = Register.GetValfromBIN(rs);
                    imm    = IR.Substring(16);
                    int imm_uval = Convert.ToInt32(imm);
                    int res      = rs_val & imm_uval;

                    Register.Registers.ElementAt <Register>(Convert.ToInt32(rt, 2)).write(res);

                    break;

                default:
                    break;
                }
            }
            else if (instruction.format == 0)
            {
                string rs = IR.Substring(6, 5);
                string rt = IR.Substring(11, 5);
                string rd = IR.Substring(16, 5);

                string sa   = IR.Substring(21, 5);
                int    rs_i = Register.GetValfromBIN(rs);
                int    rt_i = Register.GetValfromBIN(rt);
                int    sa_i = Convert.ToInt32(sa, 2);
                int    rd_n = Convert.ToInt32(rd, 2);

                //r Format;
                switch (instruction.mnemonic)
                {
                case "add":
                    //Addition with overflow
                    //rd = rs+rt
                    int val = rs_i + rt_i;
                    //Check for overflow;
                    if (overflow(val, 32))
                    {
                        OverFlow.Invoke();
                        Terminate_Error.Invoke("Overflow from instruction in PC: " + PC.ToString() + " has been detected");
                    }
                    else
                    {
                        Register.Registers.ElementAt <Register>(rd_n).write(val);

                        Excecuted.Invoke();
                    }

                    break;

                case "addu":
                    //No over Flow addition
                    //NOTE: Addu is broken down into three instructions in MARS, while here it is merely one instruction
                    val = rs_i + rt_i;
                    Register.Registers.ElementAt <Register>(rd_n).write(val);

                    Excecuted.Invoke();
                    break;

                case "and":
                    val = rs_i & rt_i;
                    Register.Registers.ElementAt <Register>(rd_n).write(val);

                    Excecuted.Invoke();
                    break;

                case "or":
                    val = rs_i | rt_i;
                    Register.Registers.ElementAt <Register>(rd_n).write(val);

                    Excecuted.Invoke();
                    break;

                case "syscall":
                    Syscall();
                    break;

                default:
                    break;
                }
            }
            //Increment Cycle
            clock++;
        }