Exemple #1
0
 private ByteBlock GetValue(Operand op)
 {
     ByteBlock result = ByteBlock.Empty;
     switch (op.Type)
     {
         case Operand.OperandType.AddressBlock:
             break;
         case Operand.OperandType.Register:
             return this.ReadRegister(op.Value.ToByte());
         case Operand.OperandType.StackIndex:
             break;
         case Operand.OperandType.NumericByte:
         case Operand.OperandType.NumericSByte:
         case Operand.OperandType.NumericShort:
         case Operand.OperandType.NumericUShort:
         case Operand.OperandType.NumericInt:
         case Operand.OperandType.NumericUInt:
         case Operand.OperandType.NumericLong:
         case Operand.OperandType.NumericULong:
         case Operand.OperandType.NumericFloat:
         case Operand.OperandType.NumericDouble:
         case Operand.OperandType.LPString:
             return op.Value;
         default:
             throw new ArgumentException();
     }
     return result;
 }
Exemple #2
0
        private void LongArithmeticInstruction(DataOpcode opcode, Operand left, Operand right, Operand dest)
        {
            if (left.Type == Operand.OperandType.LPString || right.Type == Operand.OperandType.LPString)
            {
                throw new ArgumentException("can't do arithmetic on strings");
            }
            if (dest.Type != Operand.OperandType.AddressBlock && dest.Type != Operand.OperandType.Register && dest.Type != Operand.OperandType.StackIndex)
            {
                throw new ArgumentException("can't assign to a literal");
            }

            ByteBlock op1 = GetValue(left);
            ByteBlock op2 = GetValue(right);

            ulong uresult;
            long sresult;
            double fresult;
            ByteBlock result;
            if ((left.Type == Operand.OperandType.NumericByte || left.Type == Operand.OperandType.NumericUShort ||
                 left.Type == Operand.OperandType.NumericUInt || left.Type == Operand.OperandType.NumericULong ||
                 left.Type == Operand.OperandType.Register || left.Type == Operand.OperandType.AddressBlock) &&
                (right.Type == Operand.OperandType.NumericByte || right.Type == Operand.OperandType.NumericUShort ||
                 right.Type == Operand.OperandType.NumericUInt || right.Type == Operand.OperandType.NumericULong ||
                 right.Type == Operand.OperandType.Register || right.Type == Operand.OperandType.AddressBlock)) // for now, register & memory values are only treated as ulongs.  Fix
            {
                uresult = UnsignedArithmetic(opcode, op1.ToULong(), op2.ToULong());
                if (dest.Type == Operand.OperandType.Register)
                {
                    result = new ByteBlock(uresult);
                    WriteRegister((byte)dest.Value, result);
                }
                else
                {
                //	this.Memory.WriteULongAt(uresult, (int)(((AddressBlock)dest.Value).Address)); fix
                }
            }
            else if ((left.Type == Operand.OperandType.NumericSByte || left.Type == Operand.OperandType.NumericShort ||
                      left.Type == Operand.OperandType.NumericInt || left.Type == Operand.OperandType.NumericLong) &&
                     (right.Type == Operand.OperandType.NumericSByte || right.Type == Operand.OperandType.NumericShort ||
                      right.Type == Operand.OperandType.NumericInt || right.Type == Operand.OperandType.NumericLong))
            {
                sresult = SignedArithmetic(opcode, op1.ToLong(), op2.ToLong());
                if (dest.Type == Operand.OperandType.Register)
                {
                    result = new ByteBlock(sresult);
                    WriteRegister((byte)dest.Value, result);
                }
                else
                {
                //	this.Memory.WriteLongAt(sresult, (int)(((AddressBlock)dest.Value).Address)); fix
                }
            }
            else
            {
                fresult = FPArithmetic(opcode, op1.ToDouble(), op2.ToDouble());
                if (dest.Type == Operand.OperandType.Register)
                {
                    result = new ByteBlock(fresult);
                    WriteRegister((byte)dest.Value, result);
                }
                else
                {
                //	this.Memory.WriteDoubleAt(fresult, (int)(((AddressBlock)dest.Value).Address)); fix
                }
            }
        }
Exemple #3
0
        public void Execute()
        {
            ushort fullopcode = this.ReadUShort();
            byte type = (byte)(fullopcode >> 8);
            byte opcode = (byte)((fullopcode << 8) >> 8);
            ushort arity = 0;
            switch (type)
            {
                case 0x00: // Control flow instruction
                    CFOpcode cfopcode = (CFOpcode)opcode;
                    switch (cfopcode)
                    {
                        case CFOpcode.NOP:
                            break;
                        case CFOpcode.RET:
                        case CFOpcode.END: // no operands
                            break;
                        case CFOpcode.JMP:
                        case CFOpcode.JMPA:
                        case CFOpcode.CALL:
                        case CFOpcode.CALLA: // one operand, etc
                            arity = 1;
                            break;
                        case CFOpcode.JZ:
                        case CFOpcode.JNZ:
                            arity = 2;
                            break;
                        case CFOpcode.JE:
                        case CFOpcode.JNE:
                        case CFOpcode.JLT:
                        case CFOpcode.JGT:
                        case CFOpcode.JLTE:
                        case CFOpcode.JGTE:
                            arity = 3;
                            break;
                        default:
                            throw new ArgumentOutOfRangeException(); // will likely change
                    }
                    break;
                case 0x01: // data instructions
                    DataOpcode dopcode = (DataOpcode)opcode;
                    switch (dopcode & (DataOpcode)0xE0) // seems only the top 3 bits are needed
                    {
                        case (DataOpcode)0x00: // stack arithmetic (or a move)
                            if (dopcode == DataOpcode.MOV) { arity = 2; }
                            break;
                        case (DataOpcode)0x40: // long arithmetic
                            switch (dopcode)
                            {
                                case DataOpcode.INVL:
                                case DataOpcode.NOTL:
                                case DataOpcode.BWNOTL:
                                    arity = 2;
                                    break;
                                default:
                                    if (dopcode > (DataOpcode)0x54)
                                    {
                                        throw new ArgumentOutOfRangeException();
                                    }
                                    else
                                    {
                                        arity = 3;
                                        break;
                                    }
                            }
                            break;
                        case (DataOpcode)0x80: // stack operations
                            if (dopcode == DataOpcode.ARRAYALLOC)
                            {
                                arity = 2;
                            }
                            else
                            {
                                arity = 1;
                            }
                            break;
                        case (DataOpcode)0xA0: // conversions
                            arity = 2;
                            break;
                    }
                    break;
                case 0x02: // system instructions
                    SysOpcode sopcode = (SysOpcode)opcode;
                    arity = 1;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            if (arity > 0)
            {
                Operand[] operands = new Operand[arity];
                byte flags = this.ReadByte();
                int i;
                for (i = 1; i <= arity; i++)
                {
                    switch (flags >> 6)
                    {
                        case 0: // memory addr
                            operands[i] = new Operand(this, Operand.OperandType.AddressBlock); // addressblock code to be redone
                            break;
                        case 1: // register
                            operands[i] = new Operand(this, Operand.OperandType.Register);
                            break;
                        case 2: // stack index
                            operands[i] = new Operand(this, Operand.OperandType.StackIndex);
                            break;
                        case 3: // literal
                            byte valuetype = this.ReadByte();
                            operands[i] = new Operand(this, (Operand.OperandType)(valuetype - 3));
                            break;
                    }
                    flags <<= 2;
                }
                // check operand types

            }
        }