ProgCom.CPUem.nextInst C# (CSharp) Method

nextInst() private method

private nextInst ( ) : int
return int
        private int nextInst()
        {
            //bit of background stuff
            //r0 is always locked to 0
            register[0] = 0;
            //time the instruction took to complete
            int executionTime = 0;

            //divides the instruction in usable parts
            UInt32 instruction = memory.instructionLoad(pc, out executionTime);
            long inst = (instruction & 0xfc000000) >> 26;//why do I have to declare this long?!?
            //get immediate bit
            long immed = inst >> 3;
            immed = immed & 1;
            //get instruction type bits
            long type = inst >> 4;
            inst = inst & 7;

            long regA = (instruction & 0x03e00000) >> 21;
            long regB = (instruction & 0x001f0000) >> 16;
            UInt16 address = (UInt16)(instruction & 0x0000ffff);
            long regC = (address & 0x001f);

            Int32 valA = register[regA];
            Int32 valB = register[regB];
            Int32 valC = register[regC];

            if (immed != 0) {
                valC = address;
            }
            ++pc;
            UInt64 exTmp;
            Int32 exTimeTMP;
            int tmp = 0;

            if (type == 0) { //arithmetic
                switch (inst) {
                    case 0://Add
                        exTmp = ((UInt64)valB & 0xffffffff) + ((UInt64)valC & 0xffffffff);//apparently, C# does the sign-extendy thing even when casting to ulong
                        register[exreg] = (Int32)(exTmp >> 32);
                        register[regA] = (Int32)exTmp;
                        break;
                    case 1://Sub
                        exTmp = ((UInt64)valB & 0xffffffff) + ((UInt64)(-valC) & 0xffffffff);
                        register[exreg] = (Int32)(exTmp >> 32);
                        register[regA] = (Int32)exTmp;
                        break;
                    case 2://Mul
                        exTmp = ((UInt64)valB & 0xffffffff) * ((UInt64)valC & 0xffffffff);
                        register[exreg] = (Int32)(exTmp >> 32);
                        register[regA] = (Int32)exTmp;
                        executionTime += 9;
                        break;
                    case 3://Div
                        if (valC == 0) {
                            //illegalInstructionInterrupt
                            interruptsPending.Enqueue(258);//change to dividebyzerointerrupt when available
                            register[regA] = -1;
                            register[exreg] = -1;
                            break;
                        }
                        register[exreg] = valB - (valB / valC) * valC;//this is equal to valB % valC on most systems.
                        register[regA] = valB / valC;
                        executionTime += 39;
                        break;
                    case 4://And
                        register[regA] = valB & valC;
                        break;
                    case 5://Or
                        register[regA] = valB | valC;
                        break;
                    case 6://Xor
                        register[regA] = valB ^ valC;
                        break;
                    case 7://Not
                        register[regC] = valC ^ -1;
                        break;
                }
            } else if (type == 1) { //extended arithmetic
                switch (inst) {
                    case 0://Flcmp
                        float f1 = Util.itof(valB);
                        float f2 = Util.itof(valC);
                        if (f1 < f2) {
                            register[regA] = -1;
                        } else if (f1 > f2) {
                            register[regA] = 1;
                        } else {
                            register[regA] = 0;
                        }
                        break;
                    case 1://Sr
                        if (valC != 0) {
                            register[exreg] = valB << 32 - (valC & 0x1f);
                        } else {
                            register[exreg] = 0;
                        }
                        register[regA] = (Int32)((UInt32)valB >> (valC & 0x1f));//logical right shift
                        break;
                    case 2://Sl
                        if (valC != 0) {
                            register[exreg] = (Int32)((UInt32)valB >> (32 - valC & 0x3f));
                        } else {
                            register[exreg] = 0;
                        }
                        register[regA] = valB << (valC & 0x3f);
                        break;
                    case 3://Sra
                        if (valC != 0) {
                            register[exreg] = valB << 32 - (valC & 0x1f);
                        } else {
                            register[exreg] = 0;
                        }
                        register[regA] = valB >> (valC & 0x1f);//arithmetic right shift
                        break;
                    case 4://Sx
                        spawnException(258);
                        break;
                    case 5://Float
                        tmp = floatInst(address, regA);
                        if (tmp == -1) {
                            return tmp;
                        } else {
                            executionTime += tmp;
                        }
                        break;
                    case 6://Extnd
                        tmp = extndInst(address, (Int32)regA, (Int32)regB, (Int32)regC, valA, valB, valC, immed != 0);
                        if (tmp == -1) {
                            return tmp;
                        } else {
                            executionTime += tmp;
                        }
                        break;
                    case 7://Cmp
                        if (valB < valC) {
                            register[regA] = -1;
                        } else if (valB == valC) {
                            register[regA] = 0;
                        } else {
                            register[regA] = 1;
                        }
                        break;

                }
            } else if (type == 2) { //branching
                switch (inst) {
                    case 0://Beq/Br
                        if (valA == valB) {
                            pc += (UInt16)valC;
                            executionTime += 1;
                        }
                        break;
                    case 1://Bne
                        if (valA != valB) {
                            pc += (UInt16)valC;
                            executionTime += 1;
                        }
                        break;
                    case 2://Jmpeq/Jmp
                        if (valA == valB) {
                            pc = (UInt16)valC;
                            executionTime += 1;
                            valA = 4711;//this made the jmp instruction start working for some goddamned reason. It just goes to show, when in doubt: 4711
                        }
                        break;
                    case 3://Bl
                        if (valA < valB) {
                            pc += (UInt16)valC;
                            executionTime += 1;
                        }
                        break;
                    case 4://Ble
                        if (valA <= valB) {
                            pc += (UInt16)valC;
                            executionTime += 1;
                        }
                        break;
                    case 5://Bx
                        //TODO: DO something with this instruction
                        spawnException(258);
                        break;
                    case 6://Call
                        register[15] = pc;
                        if (immed != 0) {
                            pc += (UInt16)valC;
                        } else {
                            pc = (UInt16)valC;
                        }
                        executionTime += 1;
                        break;
                    case 7://eret
                        pc = (UInt16)register[31];
                        interruptStatus.setStatus(IntStatus.IQUEUEHANDLE, true);
                        executionTime += 1;
                        break;

                }
            } else if (type == 3) { //data move
                switch (inst) {
                    case 0://Mov
                        if (immed != 0) {
                            valC += (Int32)regB << 16;
                        }
                        register[regA] = valC;
                        break;
                    case 1://Movhi
                        register[regA] = valC << 16;
                        break;
                    case 2://Rd
                        register[regA] = memory.readMem((UInt16)((valB + valC) & 0x0000ffff), out exTimeTMP);
                        executionTime += exTimeTMP - 1 + memReadDelaySlots((int)regA);
                        break;
                    case 3://Wr
                        tmp = (UInt16)((valB + valC) & 0x0000ffff);
                        executionTime += memory.writeMem(valA, (UInt16)tmp) - 1;
                        break;
                    case 4://Push
                        executionTime += memory.writeMem(valC, (UInt16)(register[14] & 0x0000ffff)) - 1;
                        register[14] = register[14] + 1;
                        break;
                    case 5://Pop
                        register[regA] = memory.readMem((UInt16)((register[14] - 1) & 0x0000ffff), out exTimeTMP);
                        register[14] = register[14] - 1;
                        executionTime += exTimeTMP - 1 + memReadDelaySlots((int)regA);
                        break;
                    case 6://Rdx
                        spawnException(258);
                        //EX = memory.readMem((UInt16)((valB + valC) & 0x0000ffff), out exTimeTMP);
                        //executionTime += exTimeTMP - 1;
                        break;
                    case 7://Int
                        spawnException(valC);
                        executionTime += 1;
                        break;

                }
            }
            return executionTime;
        }