Beispiel #1
0
 public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
 {
     XS.ClearInterruptFlag();
     XS.Set(XSRegisters.EAX, "_NATIVE_GDT_Pointer");
     XS.LoadGdt(XSRegisters.EAX, isIndirect: true);
     XS.Set(XSRegisters.EAX, XSRegisters.CR0);
     XS.Or(XSRegisters.AL, 1);
     XS.Set(XSRegisters.CR0, XSRegisters.EAX);
     XS.JumpToSegment(0x08, "PMode");
     XS.Label("PMode");
 }
Beispiel #2
0
            public static void SSEInit()
            {
                XS.Comment("BEGIN - SSE Init");

                // CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1

                XS.Set(EAX, CR4);
                XS.Or(EAX, 0x100);
                XS.Set(CR4, EAX);
                XS.Set(EAX, CR4);
                XS.Or(EAX, 0x200);
                XS.Set(CR4, EAX);
                XS.Set(EAX, CR0);
                XS.And(EAX, 0xfffffffd);
                XS.Set(CR0, EAX);
                XS.Set(EAX, CR0);

                XS.And(EAX, 1);
                XS.Set(CR0, EAX);
                XS.Comment("END - SSE Init");
            }
Beispiel #3
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackContent           = aOpCode.StackPopTypes[0];
            var xStackContentSecond     = aOpCode.StackPopTypes[1];
            var xStackContentSize       = SizeOfType(xStackContent);
            var xStackContentSecondSize = SizeOfType(xStackContentSecond);
            var xSize = Math.Max(xStackContentSize, xStackContentSecondSize);

            if (ILOp.Align(xStackContentSize, 4u) != ILOp.Align(xStackContentSecondSize, 4u))
            {
                throw new NotSupportedException("Operands have different size!");
            }
            if (xSize > 8)
            {
                throw new NotImplementedException("StackSize>8 not supported");
            }

            if (xSize > 4)
            {
                // [ESP] is low part
                // [ESP + 4] is high part
                // [ESP + 8] is low part
                // [ESP + 12] is high part
                XS.Pop(XSRegisters.EAX);
                XS.Pop(XSRegisters.EDX);
                // [ESP] is low part
                // [ESP + 4] is high part
                XS.Or(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true);
                XS.Or(XSRegisters.ESP, XSRegisters.EDX, destinationDisplacement: 4);
            }
            else
            {
                XS.Pop(XSRegisters.EAX);
                XS.Or(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true);
            }
        }
Beispiel #4
0
        public static void DoExecute(uint xStackContentSize, bool xStackContentIsFloat, string aBaseLabel)
        {
            if (xStackContentSize > 4)
            {
                if (xStackContentIsFloat)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.MulSD(XMM1, XMM0);
                    XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32)
                    string Simple32Multiply = aBaseLabel + "Simple32Multiply";
                    string MoveReturnValue  = aBaseLabel + "MoveReturnValue";

                    // right value
                    // low
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    // high
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4

                    // left value
                    // low
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8
                    // high
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12

                    // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used
                    //mov RIGHT_HIGH to eax, is useable on Full 64 multiply
                    XS.Set(EAX, ESP, sourceDisplacement: 4);
                    XS.Or(EAX, ESP, sourceDisplacement: 12);
                    XS.Jump(CPUx86.ConditionalTestEnum.Zero, Simple32Multiply);
                    // Full 64 Multiply

                    // copy again, or could change EAX
                    //TODO is there an opcode that does OR without change EAX?
                    XS.Set(EAX, ESP, sourceDisplacement: 4);
                    // eax contains already RIGHT_HIGH
                    // multiply with LEFT_LOW
                    XS.Multiply(ESP, displacement: 8);
                    // save result of LEFT_LOW * RIGHT_HIGH
                    XS.Set(ECX, EAX);

                    //mov RIGHT_LOW to eax
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    // multiply with LEFT_HIGH
                    XS.Multiply(ESP, displacement: 12);
                    // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH
                    XS.Add(ECX, EAX);

                    //mov RIGHT_LOW to eax
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    // multiply with LEFT_LOW
                    XS.Multiply(ESP, displacement: 8);
                    // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result
                    XS.Add(EDX, ECX);

                    XS.Jump(MoveReturnValue);

                    XS.Label(Simple32Multiply);
                    //mov RIGHT_LOW to eax
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    // multiply with LEFT_LOW
                    XS.Multiply(ESP, displacement: 8);

                    XS.Label(MoveReturnValue);
                    // move high result to left high
                    XS.Set(ESP, EDX, destinationDisplacement: 12);
                    // move low result to left low
                    XS.Set(ESP, EAX, destinationDisplacement: 8);
                    // pop right 64 value
                    XS.Add(ESP, 8);
                }
            }
            else
            {
                if (xStackContentIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.MulSS(XMM1, XMM0);
                    XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EAX);
                    XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32);
                    XS.Add(ESP, 4);
                    XS.Push(EAX);
                }
            }
        }
Beispiel #5
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem     = aOpCode.StackPopTypes[0];
            var xStackItemSize = SizeOfType(xStackItem);
            var xSize          = Math.Max(xStackItemSize, SizeOfType(aOpCode.StackPopTypes[1]));

            if (xSize > 4)
            {
                if (TypeIsFloat(xStackItem))
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 8);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.XorPS(XMM2, XMM2);
                    XS.SSE.DivPS(XMM1, XMM0);
                    XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true);
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

                    // divisor
                    //low
                    XS.Set(ESI, ESP, sourceIsIndirect: true);
                    //high
                    XS.Set(XSRegisters.EDI, XSRegisters.ESP, sourceDisplacement: 4);

                    //dividend
                    // low
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 8);
                    //high
                    XS.Set(XSRegisters.EDX, XSRegisters.ESP, sourceDisplacement: 12);

                    // pop both 8 byte values
                    XS.Add(XSRegisters.ESP, 16);

                    // set flags
                    XS.Or(XSRegisters.EDI, XSRegisters.EDI);
                    // if high dword of divisor is already zero, we dont need the loop
                    XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);

                    // set ecx to zero for counting the shift operations
                    XS.Xor(XSRegisters.ECX, XSRegisters.ECX);

                    XS.Label(LabelShiftRight);

                    // shift divisor 1 bit right
                    XS.ShiftRightDouble(ESI, EDI, 1);
                    XS.ShiftRight(XSRegisters.EDI, 1);

                    // increment shift counter
                    XS.Increment(XSRegisters.ECX);

                    // set flags
                    XS.Or(XSRegisters.EDI, XSRegisters.EDI);
                    // loop while high dword of divisor till it is zero
                    XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);

                    // shift the divident now in one step
                    // shift divident CL bits right
                    XS.ShiftRightDouble(EAX, EDX, CL);
                    XS.ShiftRight(XSRegisters.EDX, CL);

                    // so we shifted both, so we have near the same relation as original values
                    // divide this
                    XS.Divide(XSRegisters.ESI);

                    // save remainder to stack
                    XS.Push(0);
                    XS.Push(XSRegisters.EDX);

                    //TODO: implement proper derivation correction and overflow detection

                    XS.Jump(LabelEnd);

                    XS.Label(LabelNoLoop);

                    //save high dividend
                    XS.Set(XSRegisters.ECX, XSRegisters.EAX);
                    XS.Set(XSRegisters.EAX, XSRegisters.EDX);
                    // zero EDX, so that high part is zero -> reduce overflow case
                    XS.Xor(XSRegisters.EDX, XSRegisters.EDX);
                    // divide high part
                    XS.Divide(XSRegisters.ESI);
                    XS.Set(XSRegisters.EAX, XSRegisters.ECX);
                    // divide low part
                    XS.Divide(XSRegisters.ESI);
                    // save remainder result
                    XS.Push(0);
                    XS.Push(XSRegisters.EDX);

                    XS.Label(LabelEnd);
                }
            }
            else
            {
                if (TypeIsFloat(xStackItem))
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.XorPS(XMM2, XMM2);
                    XS.SSE.DivPS(XMM1, XMM0);
                    XS.Sub(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(XSRegisters.ECX);
                    XS.Pop(XSRegisters.EAX); // gets devised by ecx
                    XS.Xor(XSRegisters.EDX, XSRegisters.EDX);

                    XS.Divide(XSRegisters.ECX); // => EAX / ECX
                    XS.Push(XSRegisters.EDX);
                }
            }
        }
Beispiel #6
0
        public static void Assemble(Assembler aAssembler, _MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor)
        {
            // call cctor:
            if (aMethod != null)
            {
                var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? Array.Empty <ConstructorInfo>()).SingleOrDefault();
                if (xCctor != null)
                {
                    XS.Call(LabelName.Get(xCctor));
                    EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }

            if (objectType.IsValueType)
            {
                #region Valuetypes

                XS.Comment("ValueType");
                XS.Comment("Type: " + objectType);

                /*
                 * Current sitation on stack:
                 *   $ESP       Arg
                 *   $ESP+..    other items
                 *
                 * What should happen:
                 *  + The stack should be increased to allow space to contain:
                 *         + .ctor arguments
                 *         + struct _pointer_ (ref to start of emptied space)
                 *         + empty space for struct
                 *  + arguments should be copied to the new place
                 *  + old place where arguments were should be cleared
                 *  + pointer should be set
                 *  + call .ctor
                 */

                // Size of return value - we need to make room for this on the stack.
                uint xStorageSize = Align(SizeOfType(objectType), 4);
                XS.Comment("StorageSize: " + xStorageSize);
                if (xStorageSize == 0)
                {
                    throw new Exception("ValueType storage size cannot be 0.");
                }

                uint xArgSize       = 0;
                var  xParameterList = constructor.GetParameters();
                foreach (var xParam in xParameterList)
                {
                    xArgSize = xArgSize + Align(SizeOfType(xParam.ParameterType), 4);
                }
                XS.Comment("ArgSize: " + xArgSize);

                // set source of args copy
                XS.Set(ESI, ESP);

                // allocate space for struct
                XS.Sub(ESP, xStorageSize + 4);

                // set destination and count of args copy
                XS.Set(EDI, ESP);
                XS.Set(ECX, xArgSize / 4);

                // move the args to their new location
                new CPUx86.Movs {
                    Size = 32, Prefixes = CPUx86.InstructionPrefixes.Repeat
                };

                // set struct ptr
                XS.Set(EAX, ESP);
                XS.Add(EAX, xArgSize + 4);
                XS.Set(ESP, EAX, destinationDisplacement: (int)xArgSize);

                XS.Push(EAX);

                var xOpType = new OpType(xMethod.OpCode, xMethod.Position, xMethod.NextPosition, xMethod.Value.DeclaringType, xMethod.CurrentExceptionRegion);
                new Initobj(aAssembler).Execute(aMethod, xOpType);

                new Call(aAssembler).Execute(aMethod, xMethod);

                // Need to put these *after* the call because the Call pops the args from the stack
                // and we have mucked about on the stack, so this makes it right before the next
                // op.

                #endregion Valuetypes
            }
            else
            {
                // If not ValueType, then we need gc

                var xParams = constructor.GetParameters();

                // array length + 8
                bool xHasCalcSize = false;

                #region Special string handling
                // try calculating size:
                if (constructor.DeclaringType == typeof(string))
                {
                    if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char[]))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceDisplacement: 4, sourceIsIndirect: true); // address
                        XS.Set(EAX, EAX, sourceDisplacement: 8, sourceIsIndirect: true); // element count
                        XS.Set(EDX, 2);                                                  // element size
                        XS.Multiply(EDX);
                        XS.Push(EAX);
                    }
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(char[]) || xParams[0].ParameterType == typeof(char *)) &&
                             xParams[1].ParameterType == typeof(int) &&
                             xParams[2].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(EAX, 1);
                        XS.Push(EAX);
                    }
                    else if (xParams.Length == 2 &&
                             xParams[0].ParameterType == typeof(char) &&
                             xParams[1].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(EAX, 1);
                        XS.Push(EAX);
                    }

                    /*
                     * TODO see if something is needed in stack / register to make them really work
                     */
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(sbyte *) &&
                              xParams[1].ParameterType == typeof(int) &&
                              xParams[2].ParameterType == typeof(int)))
                    {
                        xHasCalcSize = true;
                        XS.Push(ESP, isIndirect: true);
                    }
                    else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(sbyte *))
                    {
                        xHasCalcSize = true;
                        /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */
                        var xSByteCountLabel = currentLabel + ".SByteCount";

                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.Or(ECX, 0xFFFFFFFF);

                        XS.Label(xSByteCountLabel);

                        XS.Increment(EAX);
                        XS.Increment(ECX);

                        XS.Compare(EAX, 0, destinationIsIndirect: true);
                        XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel);

                        XS.Push(ECX);
                    }
                    else
                    {
                        throw new NotImplementedException("In NewObj, a string ctor implementation is missing!");
                    }
                }
                #endregion Special string handling

                uint xMemSize   = GetStorageSize(objectType);
                int  xExtraSize = 12; // additional size for set values after alloc
                XS.Push((uint)(xMemSize + xExtraSize));
                if (xHasCalcSize)
                {
                    XS.Pop(EAX);
                    XS.Add(ESP, EAX, destinationIsIndirect: true);
                }

                // todo: probably we want to check for exceptions after calling Alloc
                XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
                XS.Label(".AfterAlloc");
                XS.Push(ESP, isIndirect: true);
                XS.Push(ESP, isIndirect: true);
                // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes

                // todo: use a cleaner approach here. this class shouldnt assemble the string
                string strTypeId = GetTypeIDLabel(constructor.DeclaringType);

                XS.Pop(EAX);
                XS.Set(EBX, strTypeId, sourceIsIndirect: true);
                XS.Set(EAX, EBX, destinationIsIndirect: true);
                XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.NormalObject, destinationDisplacement: 4, destinationIsIndirect: true, size: RegisterSize.Int32);
                XS.Set(EAX, xMemSize, destinationDisplacement: 8, destinationIsIndirect: true, size: RegisterSize.Int32);
                uint xSize = (uint)(from item in xParams
                                    let xQSize = Align(SizeOfType(item.ParameterType), 4)
                                                 select(int) xQSize).Take(xParams.Length).Sum();
                XS.Push(0);

                foreach (var xParam in xParams)
                {
                    uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4);
                    XS.Comment($"Arg {xParam.Name}: {xParamSize}");
                    for (int i = 0; i < xParamSize; i += 4)
                    {
                        XS.Push(ESP, isIndirect: true, displacement: (int)(xSize + 8));
                    }
                }


                XS.Call(LabelName.Get(constructor));
                // should the complete error handling happen by ILOp.EmitExceptionLogic?
                if (aMethod != null)
                {
                    // todo: only happening for real methods now, not for ctor's ?
                    XS.Test(ECX, 2);
                    string xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString();
                    XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel);

                    PushAlignedParameterSize(constructor);

                    // an exception occurred, we need to cleanup the stack, and jump to the exit
                    XS.Add(ESP, 4);

                    new Comment(aAssembler, "[ Newobj.Execute cleanup end ]");
                    Jump_Exception(aMethod);
                    XS.Label(xNoErrorLabel);
                }
                XS.Pop(EAX);

                PushAlignedParameterSize(constructor);

                XS.Push(EAX);
                XS.Push(0);
            }
        }
Beispiel #7
0
            public override void AssembleNew(object aAssembler, object aMethodInfo)
            {
                XS.Mov(XSRegisters.BL, 0xa8);

                XS.Call("send_mouse_cmd");

                XS.Call("mouse_read");

                XS.Noop();

                XS.Mov(XSRegisters.BL, 0x20);

                XS.Call("send_mouse_cmd");

                XS.Call("mouse_read");

                XS.Or(XSRegisters.AL, 3);

                XS.Mov(XSRegisters.BL, 0x60);

                XS.Push(XSRegisters.EAX);

                XS.Call("send_mouse_cmd");

                XS.Pop(XSRegisters.EAX);

                XS.Call("mouse_write");

                XS.Noop();

                XS.Mov(XSRegisters.BL, 0xd4);

                XS.Call("send_mouse_cmd");

                XS.Mov(XSRegisters.AL, 0xf4);

                XS.Call("mouse_write");

                XS.Call("mouse_read");

                #region mouse_read
                XS.Label("mouse_read");
                {
                    XS.Push(XSRegisters.ECX);

                    XS.Push(XSRegisters.EDX);

                    XS.Mov(XSRegisters.ECX, 0xffff);

                    XS.Label("mouse_read_loop");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 1);

                        XS.Jump(ConditionalTestEnum.NotZero, "mouse_read_ready");

                        new Loop
                        {
                            DestinationLabel = "mouse_read_loop"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_read_exit");
                    }

                    XS.Label("mouse_read_ready");
                    {
                        XS.Push(XSRegisters.ECX);

                        XS.Mov(XSRegisters.ECX, 32);
                    }

                    XS.Label("mouse_read_delay");
                    {
                        new Loop
                        {
                            DestinationLabel = "mouse_read_delay"
                        };

                        XS.Pop(XSRegisters.ECX);

                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x60,
                            Size           = 8
                        };

                        XS.Xor(XSRegisters.AH, XSRegisters.RegistersEnum.AH);
                    }

                    XS.Label("mouse_read_exit");
                    {
                        XS.Pop(XSRegisters.EDX);

                        XS.Pop(XSRegisters.ECX);

                        XS.Return();
                    }
                }
                #endregion

                #region mouse_write
                XS.Label("mouse_write");
                {
                    XS.Push(XSRegisters.ECX);

                    XS.Push(XSRegisters.EDX);

                    XS.Mov(XSRegisters.BH, XSRegisters.RegistersEnum.AL);

                    XS.Mov(XSRegisters.ECX, 0xffff);

                    XS.Label("mouse_write_loop1");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 32);

                        XS.Jump(ConditionalTestEnum.Zero, "mouse_write_ok1");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop1"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_write_exit");
                    }

                    XS.Label("mouse_write_ok1");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x60,
                            Size           = 8
                        };

                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_write_loop");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 2);

                        XS.Jump(ConditionalTestEnum.Zero, "mouse_write_ok");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_write_exit");
                    }

                    XS.Label("mouse_write_ok");
                    {
                        XS.Mov(XSRegisters.AL, XSRegisters.RegistersEnum.BH);

                        new Out2Port
                        {
                            DestinationValue = 0x60,
                            SourceReg        = RegistersEnum.AL,
                            Size             = 8
                        };

                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_write_loop3");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 2);

                        XS.Jump(ConditionalTestEnum.Zero, "mouse_write_ok3");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop3"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_write_exit");
                    }

                    XS.Label("mouse_write_ok3");
                    {
                        XS.Mov(XSRegisters.AH, 0x08);
                    }

                    XS.Label("mouse_write_loop4");
                    {
                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_write_loop5");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 1);

                        XS.Jump(ConditionalTestEnum.NotZero, "mouse_write_ok4");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop5"
                        };

                        XS.Dec(XSRegisters.AH);

                        XS.Jump(ConditionalTestEnum.NotZero, "mouse_write_loop4");
                    }

                    XS.Label("mouse_write_ok4");
                    {
                        XS.Xor(XSRegisters.AH, XSRegisters.RegistersEnum.AH);
                    }

                    XS.Label("mouse_write_exit");
                    {
                        XS.Pop(XSRegisters.EDX);

                        XS.Pop(XSRegisters.ECX);

                        XS.Return();
                    }
                }
                #endregion

                #region send_mouse_cmd
                XS.Label("send_mouse_cmd");
                {
                    XS.Mov(XSRegisters.ECX, 0xffff);

                    XS.Label("mouse_cmd_wait");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };
                        XS.Test(XSRegisters.AL, 2);
                        XS.Jump(ConditionalTestEnum.Zero, "mouse_cmd_send");
                        new Loop
                        {
                            DestinationLabel = "mouse_cmd_wait"
                        };
                        XS.Jump("mouse_cmd_error");
                    }

                    XS.Label("mouse_cmd_send");
                    {
                        XS.Mov(XSRegisters.AL, XSRegisters.RegistersEnum.BL);
                        new Out2Port
                        {
#if DebugMouse
                            SourceValue    = 0x64,
                            DestinationReg = RegistersEnum.AL,
#else
                            DestinationValue = 0x64,
                            SourceReg        = RegistersEnum.AL,
#endif
                            Size = 8
                        };
                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_cmd_accept");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };
                        XS.Test(XSRegisters.AL, 0x02);
                        XS.Jump(ConditionalTestEnum.Zero, "mouse_cmd_ok");
                        new Loop
                        {
                            DestinationLabel = "mouse_cmd_accept"
                        };
                    }

                    XS.Label("mouse_cmd_error");
                    {
                        XS.Mov(XSRegisters.AH, 0x01);
                        XS.Jump("mouse_cmd_exit");
                    }

                    XS.Label("mouse_cmd_ok");
                    {
                        XS.Xor(XSRegisters.AH, XSRegisters.RegistersEnum.AH);
                    }

                    XS.Label("mouse_cmd_exit");
                    {
                        XS.Return();
                    }
                }
                #endregion
            }
Beispiel #8
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem      = aOpCode.StackPopTypes[0];
            var xStackItemSize  = SizeOfType(xStackItem);
            var xStackItem2     = aOpCode.StackPopTypes[1];
            var xStackItem2Size = SizeOfType(xStackItem2);

            if (xStackItemSize == 8)
            {
                // there seem to be an error in MS documentation, there is pushed an int32, but IL shows else
                if (xStackItem2Size != 8)
                {
                    throw new Exception("Cosmos.IL2CPU.x86->IL->Div.cs->Error: Expected a size of 8 for Div!");
                }
                if (TypeIsFloat(xStackItem))
                {
                    // TODO add 0/0 infinity/infinity X/infinity
                    // value 1
                    new CPUx86.x87.FloatLoad {
                        DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8
                    };
                    // value 2
                    new CPUx86.x87.FloatDivide {
                        DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 64
                    };
                    // override value 1
                    new CPUx86.x87.FloatStoreAndPop {
                        DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8
                    };
                    // pop value 2
                    XS.Add(XSRegisters.ESP, 8);
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

                    // divisor
                    //low
                    XS.Set(ESI, ESP, sourceIsIndirect: true);
                    //high
                    XS.Set(XSRegisters.EDI, XSRegisters.ESP, sourceDisplacement: 4);

                    //dividend
                    // low
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 8);
                    //high
                    XS.Set(XSRegisters.EDX, XSRegisters.ESP, sourceDisplacement: 12);

                    // pop both 8 byte values
                    XS.Add(XSRegisters.ESP, 16);

                    // set flags
                    XS.Or(XSRegisters.EDI, XSRegisters.EDI);
                    // if high dword of divisor is already zero, we dont need the loop
                    XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);

                    // set ecx to zero for counting the shift operations
                    XS.Xor(XSRegisters.ECX, XSRegisters.ECX);

                    XS.Label(LabelShiftRight);

                    // shift divisor 1 bit right
                    XS.ShiftRightDouble(ESI, EDI, 1);

                    XS.ShiftRight(XSRegisters.EDI, 1);

                    // increment shift counter
                    XS.Increment(XSRegisters.ECX);

                    // set flags
                    XS.Or(XSRegisters.EDI, XSRegisters.EDI);
                    // loop while high dword of divisor till it is zero
                    XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);

                    // shift the divident now in one step
                    // shift divident CL bits right
                    XS.ShiftRightDouble(EAX, EDX, CL);
                    XS.ShiftRight(XSRegisters.EDX, CL);

                    // so we shifted both, so we have near the same relation as original values
                    // divide this
                    XS.Divide(XSRegisters.ESI);

                    // save result to stack
                    XS.Push(0);
                    XS.Push(XSRegisters.EAX);

                    //TODO: implement proper derivation correction and overflow detection

                    XS.Jump(LabelEnd);

                    XS.Label(LabelNoLoop);

                    //save high dividend
                    XS.Set(XSRegisters.ECX, XSRegisters.EAX);
                    XS.Set(XSRegisters.EAX, XSRegisters.EDX);
                    // zero EDX, so that high part is zero -> reduce overflow case
                    XS.Xor(XSRegisters.EDX, XSRegisters.EDX);
                    // divide high part
                    XS.Divide(XSRegisters.ESI);
                    // save high result
                    XS.Push(XSRegisters.EAX);
                    XS.Set(XSRegisters.EAX, XSRegisters.ECX);
                    // divide low part
                    XS.Divide(XSRegisters.ESI);
                    // save low result
                    XS.Push(XSRegisters.EAX);

                    XS.Label(LabelEnd);
                }
            }
            else
            {
                if (TypeIsFloat(xStackItem))
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.MulSS(XMM0, XMM1);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                }
                else
                {
                    XS.Xor(XSRegisters.EDX, XSRegisters.EDX);
                    XS.Pop(XSRegisters.ECX);
                    XS.Pop(XSRegisters.EAX);
                    XS.Divide(XSRegisters.ECX);
                    XS.Push(XSRegisters.EAX);
                }
            }
        }
Beispiel #9
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem      = aOpCode.StackPopTypes[0];
            var xStackItemSize  = SizeOfType(xStackItem);
            var xStackItem2     = aOpCode.StackPopTypes[0];
            var xStackItem2Size = SizeOfType(xStackItem2);

            if (xStackItemSize == 8)
            {
                // there seem to be an error in MS documentation, there is pushed an int32, but IL shows else
                if (xStackItem2Size != 8)
                {
                    throw new Exception("Cosmos.IL2CPU.x86->IL->Div.cs->Error: Expected a size of 8 for Div!");
                }
                if (TypeIsFloat(xStackItem))
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.DivSD(XMM1, XMM0);
                    XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

                    // divisor
                    //low
                    XS.Set(ESI, ESP, sourceIsIndirect: true);
                    //high
                    XS.Set(EDI, ESP, sourceDisplacement: 4);

                    // pop both 8 byte values
                    XS.Add(ESP, 8);

                    //dividend
                    // low
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    //high
                    XS.Set(EDX, ESP, sourceDisplacement: 4);

                    XS.Add(ESP, 8);

                    // set flags
                    XS.Or(EDI, EDI);
                    // if high dword of divisor is already zero, we dont need the loop
                    XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);

                    // set ecx to zero for counting the shift operations
                    XS.Xor(ECX, ECX);

                    XS.Label(LabelShiftRight);

                    // shift divisor 1 bit right
                    XS.ShiftRightDouble(ESI, EDI, 1);
                    XS.ShiftRight(EDI, 1);

                    // increment shift counter
                    XS.Increment(ECX);

                    // set flags
                    XS.Or(EDI, EDI);
                    // loop while high dword of divisor till it is zero
                    XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);

                    // shift the divident now in one step
                    // shift divident CL bits right
                    XS.ShiftRightDouble(EAX, EDX, CL);
                    XS.ShiftRight(EDX, CL);

                    // so we shifted both, so we have near the same relation as original values
                    // divide this
                    XS.IntegerDivide(ESI);

                    // sign extend
                    XS.SignExtendAX(RegisterSize.Int32);

                    // save result to stack
                    XS.Push(EDX);
                    XS.Push(EAX);

                    //TODO: implement proper derivation correction and overflow detection

                    XS.Jump(LabelEnd);

                    XS.Label(LabelNoLoop);
                    //save high dividend
                    XS.Set(ECX, EAX);
                    XS.Set(EAX, EDX);
                    // extend that sign is in edx
                    XS.SignExtendAX(RegisterSize.Int32);
                    // divide high part
                    XS.IntegerDivide(ESI);
                    // save high result
                    XS.Push(EAX);
                    XS.Set(EAX, ECX);
                    // divide low part
                    XS.Divide(ESI);
                    // save low result
                    XS.Push(EAX);

                    XS.Label(LabelEnd);
                }
            }
            else
            {
                if (TypeIsFloat(xStackItem))
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(XSRegisters.ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.DivSS(XMM1, XMM0);
                    XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(XSRegisters.ECX);
                    XS.Pop(XSRegisters.EAX);
                    XS.SignExtendAX(RegisterSize.Int32);
                    XS.IntegerDivide(XSRegisters.ECX);
                    XS.Push(XSRegisters.EAX);
                }
            }
        }
Beispiel #10
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem = aOpCode.StackPopTypes[0];
            var xSize      = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1]));
            var xIsFloat   = TypeIsFloat(xStackItem);
            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException";

            if (xSize > 8)
            {
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div.cs->Error: StackSize > 8 not supported");
            }
            else if (xSize > 4)
            {
                if (xIsFloat)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.DivSD(XMM1, XMM0);
                    XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

                    // divisor
                    // low
                    XS.Pop(ESI);
                    // high
                    XS.Pop(EDI);

                    XS.Xor(EAX, EAX);
                    XS.Or(EAX, ESI);
                    XS.Or(EAX, EDI);
                    XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel);

                    XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef));

                    XS.Label(xNoDivideByZeroExceptionLabel);

                    // dividend
                    // low
                    XS.Pop(EAX);
                    // high
                    XS.Pop(EDX);

                    // set flags
                    XS.Or(EDI, EDI);
                    // if high dword of divisor is already zero, we dont need the loop
                    XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop);

                    // set ecx to zero for counting the shift operations
                    XS.Xor(ECX, ECX);

                    // push most significant bit of result
                    XS.Set(EBX, EDI);
                    XS.Xor(EBX, EDX);
                    XS.Push(EBX);

                    XS.Compare(EDI, 0x80000000);
                    XS.Jump(ConditionalTestEnum.Below, BaseLabel + "divisor_no_neg");

                    XS.Negate(ESI);
                    XS.AddWithCarry(EDI, 0);
                    XS.Negate(EDI);

                    XS.Label(BaseLabel + "divisor_no_neg");

                    XS.Compare(EDX, 0x80000000);
                    XS.Jump(ConditionalTestEnum.Below, BaseLabel + "dividend_no_neg");

                    XS.Negate(EAX);
                    XS.AddWithCarry(EDX, 0);
                    XS.Negate(EDX);

                    XS.Label(BaseLabel + "dividend_no_neg");

                    XS.Label(LabelShiftRight);

                    // shift divisor 1 bit right
                    XS.ShiftRightDouble(ESI, EDI, 1);
                    XS.ShiftRight(EDI, 1);

                    // increment shift counter
                    XS.Increment(ECX);

                    // set flags
                    //XS.Or(EDI, EDI);
                    XS.Set(EBX, ESI);
                    XS.And(EBX, 0x80000000);
                    XS.Or(EBX, EDI);
                    // loop while high dword of divisor is not zero or most significant bit of low dword of divisor is set
                    XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight);

                    // shift the dividend now in one step
                    XS.ShiftRightDouble(EAX, EDX, CL);
                    // shift dividend CL bits right
                    XS.ShiftRight(EDX, CL);

                    // so we shifted both, so we have near the same relation as original values
                    // divide this
                    XS.IntegerDivide(ESI);

                    // pop most significant bit of result
                    XS.Pop(EBX);

                    XS.Compare(EBX, 0x80000000);
                    XS.Jump(ConditionalTestEnum.Below, BaseLabel + "_result_no_neg");

                    XS.Negate(EAX);

                    XS.Label(BaseLabel + "_result_no_neg");

                    // sign extend
                    XS.SignExtendAX(RegisterSize.Int32);

                    // save result to stack
                    XS.Push(EDX);
                    XS.Push(EAX);

                    //TODO: implement proper derivation correction and overflow detection

                    XS.Jump(LabelEnd);

                    XS.Label(LabelNoLoop);
                    // save high dividend
                    XS.Set(ECX, EAX);
                    XS.Set(EAX, EDX);

                    // extend that sign is in edx
                    XS.SignExtendAX(RegisterSize.Int32);
                    // divide high part
                    XS.IntegerDivide(ESI);
                    // save high result
                    XS.Push(EAX);
                    XS.Set(EAX, ECX);
                    // divide low part
                    XS.Divide(ESI);
                    // save low result
                    XS.Push(EAX);

                    XS.Label(LabelEnd);
                }
            }
            else
            {
                if (xIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.DivSS(XMM1, XMM0);
                    XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(ECX);

                    XS.Test(ECX, ECX);
                    XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel);

                    XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef));

                    XS.Label(xNoDivideByZeroExceptionLabel);

                    XS.Pop(EAX);

                    XS.SignExtendAX(RegisterSize.Int32);

                    XS.IntegerDivide(ECX);
                    XS.Push(EAX);
                }
            }
        }
Beispiel #11
0
 public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.Mov(XSRegisters.EAX, XSRegisters.CPUx86.Registers.CR0);
     XS.Or(XSRegisters.EAX, 0x80000000);
     XS.Mov(XSRegisters.CR0, XSRegisters.CPUx86.Registers.EAX);
 }
Beispiel #12
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem = aOpCode.StackPopTypes[0];
            var xSize      = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1]));
            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException";

            if (TypeIsFloat(xStackItem))
            {
                throw new Exception("Cosmos.IL2CPU.x86->IL->Div_Un.cs->Error: Expected unsigned integer operands but got float!");
            }

            if (xSize > 8)
            {
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div_Un.cs->Error: StackSize > 8 not supported");
            }
            else if (xSize > 4)
            {
                string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                string LabelNoLoop     = BaseLabel + "NoLoop";
                string LabelEnd        = BaseLabel + "End";

                // divisor
                // low
                XS.Pop(ESI);
                // high
                XS.Pop(EDI);

                XS.Xor(EAX, EAX);
                XS.Or(EAX, ESI);
                XS.Or(EAX, EDI);
                XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel);

                XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef));

                XS.Label(xNoDivideByZeroExceptionLabel);

                // dividend
                // low
                XS.Pop(EAX);
                // high
                XS.Pop(EDX);

                // set flags
                XS.Or(EDI, EDI);
                // if high dword of divisor is already zero, we dont need the loop
                XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop);

                // set ecx to zero for counting the shift operations
                XS.Xor(ECX, ECX);

                XS.Label(LabelShiftRight);

                // shift divisor 1 bit right
                XS.ShiftRightDouble(ESI, EDI, 1);
                XS.ShiftRight(EDI, 1);

                // increment shift counter
                XS.Increment(ECX);

                // set flags
                XS.Or(EDI, EDI);
                // loop while high dword of divisor till it is zero
                XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight);

                // shift the dividend now in one step
                // shift dividend CL bits right
                XS.ShiftRightDouble(EAX, EDX, CL);
                XS.ShiftRight(EDX, CL);

                // so we shifted both, so we have near the same relation as original values
                // divide this
                XS.Divide(ESI);

                // save result to stack
                XS.Push(0);
                XS.Push(EAX);

                //TODO: implement proper derivation correction and overflow detection

                XS.Jump(LabelEnd);

                XS.Label(LabelNoLoop);

                //save high dividend
                XS.Set(ECX, EAX);
                XS.Set(EAX, EDX);
                // zero EDX, so that high part is zero -> reduce overflow case
                XS.Xor(EDX, EDX);
                // divide high part
                XS.Divide(ESI);
                // save high result
                XS.Push(EAX);
                XS.Set(EAX, ECX);
                // divide low part
                XS.Divide(ESI);
                // save low result
                XS.Push(EAX);

                XS.Label(LabelEnd);
            }
            else
            {
                XS.Pop(ECX);

                XS.Test(ECX, ECX);
                XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel);

                XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef));

                XS.Label(xNoDivideByZeroExceptionLabel);

                XS.Pop(EAX);

                XS.Xor(EDX, EDX);

                XS.Divide(ECX);
                XS.Push(EAX);
            }
        }