Skip to content
Browse files

- More Work

  • Loading branch information...
1 parent 9eb9bb4 commit 25c8765ed1e940b72a66a26a21d256115dc1e129 @soywiz committed Apr 2, 2012
View
3 DotX86/.gitignore
@@ -0,0 +1,3 @@
+
+*.psess
+*.vsp
View
65 DotX86/DotX86/Core/Cpu/Dynarec/MethodGenerator.cs
@@ -205,11 +205,47 @@ private bool EmitInstruction(uint PC, uint nPC, Instruction Instruction, ILGener
LoadValue(Instruction.Value);
CallFunction((REF_DWORD_DELEGATE)Operations.ADD_DWORD);
break;
- default:
+ case InstructionType.RegisterRegister:
LoadRegisterAddress(Instruction.Register1);
LoadRegisterValue(Instruction.Register2);
CallFunction((REF_DWORD_DELEGATE)Operations.ADD_DWORD);
break;
+ default:
+ throw (new NotImplementedException());
+ }
+ }
+ break;
+ case Opcode.SHL:
+ {
+ switch (Instruction.Type)
+ {
+ case InstructionType.RegisterValue:
+ LoadRegisterAddress(Instruction.Register1);
+ LoadValue(Instruction.Value);
+ CallFunction((REF_DWORD_DELEGATE)Operations.SHL_DWORD);
+ break;
+ case InstructionType.RegisterRegister:
+ LoadRegisterAddress(Instruction.Register1);
+ LoadRegisterValue(Instruction.Register2);
+ CallFunction((REF_DWORD_DELEGATE)Operations.SHL_DWORD);
+ break;
+ default:
+ throw(new NotImplementedException());
+ }
+ }
+ break;
+ case Opcode.TEST:
+ {
+ switch (Instruction.Type)
+ {
+ case InstructionType.RegisterRegister:
+ LoadThreadContext();
+ LoadRegisterValue(Instruction.Register1);
+ LoadRegisterValue(Instruction.Register2);
+ CallFunction((Action<ThreadContext, int, int>)Operations.TEST_DWORD);
+ break;
+ default:
+ throw (new NotImplementedException());
}
}
break;
@@ -243,6 +279,8 @@ private bool EmitInstruction(uint PC, uint nPC, Instruction Instruction, ILGener
return false;
}
+ case Opcode.JZ:
+ case Opcode.JNZ:
case Opcode.JGE:
{
switch (Instruction.Type)
@@ -251,13 +289,36 @@ private bool EmitInstruction(uint PC, uint nPC, Instruction Instruction, ILGener
LoadThreadContext();
LoadValue((uint)(nPC));
LoadValue((uint)(nPC + Instruction.Value));
- CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_GREATER_EQUAL);
+ switch (Instruction.Opcode)
+ {
+ case Opcode.JZ: CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_ZERO); break;
+ case Opcode.JNZ: CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_NOT_ZERO); break;
+ case Opcode.JGE: CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_GREATER_EQUAL); break;
+ default: throw (new NotImplementedException());
+ }
+
break;
default:
throw (new NotImplementedException());
}
return false;
}
+ // idiv — Integer Division
+ // The idiv instruction divides the contents of the 64 bit integer EDX:EAX
+ // (constructed by viewing EDX as the most significant four bytes and EAX as
+ // the least significant four bytes) by the specified operand value. The quotient
+ // result of the division is stored into EAX, while the remainder is placed in EDX.
+ case Opcode.IDIV:
+ {
+ LoadThreadContext();
+ CallFunction((Action<ThreadContext>)Operations.IDIV);
+ }
+ break;
+ case Opcode.CDQ:
+ {
+ LoadThreadContext();
+ CallFunction((Action<ThreadContext>)Operations.CONVERT_DWORD_TO_QWORD);
+ }
break;
case Opcode.JMP:
{
View
62 DotX86/DotX86/Core/Cpu/Dynarec/Operations.Comparison.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotX86.Core.Cpu.Dynarec
+{
+ public partial class Operations
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="ThreadContext"></param>
+ /// <param name="Left"></param>
+ /// <param name="Right"></param>
+ static public void CMP_DWORD(ThreadContext ThreadContext, int Left, int Right)
+ {
+ int Result;
+
+ Result = Left - Right;
+
+ //Console.WriteLine("######## CMP: 0x{1:X} - 0x{2:X} = 0x{0:X}", Result, Left, Right);
+
+ ThreadContext.Flags.OF = false;
+ ThreadContext.Flags.ZF = (Result == 0);
+ ThreadContext.Flags.SF = (Result < 0);
+
+ //if (Right < Left) ThreadContext.Flags.OF = true;
+
+ try
+ {
+ Result = checked(Left - Right);
+ }
+ catch (OverflowException)
+ {
+ ThreadContext.Flags.OF = true;
+ }
+ }
+
+ /// <summary>
+ /// In the x86 assembly language, the TEST instruction performs a bitwise AND on two operands.
+ /// The flags SF, ZF, PF, CF, OF and AF are modified while the result of the AND is discarded.
+ /// There are 9 different opcodes for the TEST instruction depending on the type and size of the operands.
+ /// It can compare 8-bit, 16-bit, 32-bit or 64-bit values. It can also compare registers, immediate values and register indirect values.[1]
+ /// </summary>
+ /// <param name="ThreadContext"></param>
+ /// <param name="Left"></param>
+ /// <param name="Right"></param>
+ /// <see cref="http://en.wikipedia.org/wiki/TEST_(x86_instruction)"/>
+ static public void TEST_DWORD(ThreadContext ThreadContext, int Left, int Right)
+ {
+ var Result = (Left & Right);
+
+ ThreadContext.Flags.ZF = (Result == 0);
+
+ // @TODO
+ //SF, ZF, PF, CF, OF and AF
+ //throw new NotImplementedException();
+ }
+ }
+}
View
58 DotX86/DotX86/Core/Cpu/Dynarec/Operations.Memory.cs
@@ -57,28 +57,10 @@ static public void ADD_DWORD(ref uint Pointer, uint Value)
Pointer += Value;
}
- static public void CMP_DWORD(ThreadContext ThreadContext, int Left, int Right)
+ static public void SHL_DWORD(ref uint Pointer, uint Value)
{
- int Result;
-
- Result = Left - Right;
-
- //Console.WriteLine("######## CMP: 0x{1:X} - 0x{2:X} = 0x{0:X}", Result, Left, Right);
-
- ThreadContext.Flags.OF = false;
- ThreadContext.Flags.ZF = (Result == 0);
- ThreadContext.Flags.SF = (Result < 0);
-
- //if (Right < Left) ThreadContext.Flags.OF = true;
-
- try
- {
- Result = checked(Left - Right);
- }
- catch (OverflowException)
- {
- ThreadContext.Flags.OF = true;
- }
+ //Console.WriteLine("({0})", Value);
+ Pointer <<= (int)Value;
}
static public void XCHG_DWORD(ref uint Left, ref uint Right)
@@ -105,19 +87,20 @@ static public void JUMP(ThreadContext ThreadContext, uint JumpAddress)
ThreadContext.PC = JumpAddress;
}
- internal static void JUMP_GREATER_EQUAL(ThreadContext ThreadContext, uint CurrentAddress, uint JumpAddress)
+ internal static void JUMP_ZERO(ThreadContext ThreadContext, uint CurrentAddress, uint JumpAddress)
{
- // SignFlag == OverflowFlag
- if (ThreadContext.Flags.SF == ThreadContext.Flags.OF)
- {
- ThreadContext.PC = JumpAddress;
- }
- else
- {
- ThreadContext.PC = CurrentAddress;
- }
+ ThreadContext.PC = (ThreadContext.Flags.ZF) ? JumpAddress : CurrentAddress;
+ }
+
+ internal static void JUMP_NOT_ZERO(ThreadContext ThreadContext, uint CurrentAddress, uint JumpAddress)
+ {
+ ThreadContext.PC = (!ThreadContext.Flags.ZF) ? JumpAddress : CurrentAddress;
}
+ internal static void JUMP_GREATER_EQUAL(ThreadContext ThreadContext, uint CurrentAddress, uint JumpAddress)
+ {
+ ThreadContext.PC = (ThreadContext.Flags.SF == ThreadContext.Flags.OF) ? JumpAddress : CurrentAddress;
+ }
static public void RETURN(ThreadContext ThreadContext)
{
@@ -176,5 +159,18 @@ static public void TRACE1(ThreadContext ThreadContext, uint PC, string Instructi
{
Console.WriteLine(" | $$ {0}", ThreadContext);
}
+
+ static public void CONVERT_DWORD_TO_QWORD(ThreadContext ThreadContext)
+ {
+ ThreadContext.EDX_EAX = (long)(int)ThreadContext.EAX;
+ }
+
+ static public void IDIV(ThreadContext ThreadContext)
+ {
+ var Numerator = ThreadContext.EDX_EAX;
+ var Denominator = ThreadContext.ECX;
+ ThreadContext.EAX = (uint)(Numerator / Denominator);
+ ThreadContext.EDX = (uint)(Numerator % Denominator);
+ }
}
}
View
132 DotX86/DotX86/Core/Cpu/Tables/InstructionDecoder.cs
@@ -90,15 +90,18 @@ static public Instruction DecodeInstruction_0F(uint PC, BinaryReader Reader)
var Byte = Reader.ReadByte();
switch (Byte)
{
+ // JZ
+ case 0x84: { var Value = Reader.ReadInt32(); return Instruction(Opcode.JZ, (uint)Value); }
+ // JNZ
+ case 0x85: { var Value = Reader.ReadInt32(); return Instruction(Opcode.JNZ, (uint)Value); }
+
// JNL / JGE
// http://en.wikibooks.org/wiki/X86_Assembly/Control_Flow
case 0x8D:
{
var Value = Reader.ReadInt32();
return Instruction(Opcode.JGE, (uint)Value);
}
- throw (new NotImplementedException());
- break;
default: throw (new NotImplementedException(String.Format("Unknown instruction with opcode 0x0F + 0x{0:X} at 0x{1:X}", Byte, PC)));
}
}
@@ -181,22 +184,45 @@ static public Instruction DecodeInstruction(uint PC, BinaryReader Reader)
throw (new NotImplementedException());
}
}
+
+ // TEST Ew,Gw
+ case 0x85:
+ {
+ var Param = Reader.ReadByte();
+ var Left = ((Param >> 0) & 7);
+ var Right = ((Param >> 3) & 7);
+ return Instruction(Opcode.TEST, (Register)Left, (Register)Right);
+ }
+
+ // MOV Eb,Gb
+ case 0x88:
+ {
+ throw (new NotImplementedException());
+ }
+
// MOV Ew,Gw
case 0x89:
{
var Param = Reader.ReadByte();
var Left = ((Param >> 0) & 7);
var Right = ((Param >> 3) & 7);
+ var Info = (Param >> 6) & 3;
// MOV REG1, REG2
- if (Param >= 0xC0)
+ if (Info == 3)
{
return Instruction(Opcode.MOV, (Register)Left, (Register)Right);
}
// MOV [REG1 + X], REG2
else
{
- var Offset = Reader.ReadSByte();
+ int Offset = 0;
+ switch (Info)
+ {
+ case 0: break;
+ case 1: Offset = Reader.ReadSByte(); break;
+ default: throw (new NotImplementedException());
+ }
return Instruction(Opcode.MOV, (Register)Left, Offset, (Register)Right);
}
}
@@ -206,20 +232,26 @@ static public Instruction DecodeInstruction(uint PC, BinaryReader Reader)
var Param = Reader.ReadByte();
var Right = (Register)((Param >> 0) & 7);
var Left = (Register)((Param >> 3) & 7);
+ var Info = (Param >> 6) & 3;
// MOV REG1, REG2
- if (Param >= 0xC0)
+ if (Info == 3)
{
throw(new NotImplementedException());
}
// MOV [REG1 + X], REG2
else
{
- var Offset = Reader.ReadSByte();
+ int Offset = 0;
+ switch (Info)
+ {
+ case 0: break;
+ case 1: Offset = Reader.ReadSByte(); break;
+ default: throw(new NotImplementedException());
+ }
return Instruction(Opcode.MOV, (Register)Left, (Register)Right, Offset);
}
}
- break;
// LEA Gw
case 0x8D:
{
@@ -243,6 +275,12 @@ static public Instruction DecodeInstruction(uint PC, BinaryReader Reader)
return Instruction(Opcode.XCHG, (Register)(Byte - 0x90), Register.AX);
}
+ // CDQ
+ case 0x99:
+ {
+ return Instruction(Opcode.CDQ);
+ }
+
// MOV AX,Iw
case 0xB8:
case 0xB9:
@@ -256,6 +294,65 @@ static public Instruction DecodeInstruction(uint PC, BinaryReader Reader)
var Value = Reader.ReadUInt32();
return Instruction(Opcode.MOV, (Register)(Byte - 0xB8), Value);
}
+
+ // GRP2 Ew,Ib
+ case 0xC1:
+ {
+ var Param = Reader.ReadByte();
+ var Which = (Param >> 3) & 7;
+ var Left = (Register)((Param >> 0) & 7);
+
+ if (Param >= 0xC0)
+ {
+ var Value = (uint)(int)Reader.ReadSByte();
+
+ switch (Which)
+ {
+ case 4:
+ case 5: return Instruction(Opcode.SHL, Left, Value);
+ default: throw (new NotImplementedException());
+ }
+ }
+ else
+ {
+ throw (new NotImplementedException());
+ }
+
+ /*
+ if (Param >= 0xc0)
+ {
+ GetEArw;
+ Bit8u val=blah & 0x1f;
+ switch (which) {
+ case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break;
+ case 0x01:RORW(*earw,val,LoadRw,SaveRw);break;
+ case 0x02:RCLW(*earw,val,LoadRw,SaveRw);break;
+ case 0x03:RCRW(*earw,val,LoadRw,SaveRw);break;
+ case 0x04:// SHL and SAL are the same
+ case 0x06:SHLW(*earw,val,LoadRw,SaveRw);break;
+ case 0x05:SHRW(*earw,val,LoadRw,SaveRw);break;
+ case 0x07:SARW(*earw,val,LoadRw,SaveRw);break;
+ }
+ }
+ else
+ {
+ GetEAa;
+ Bit8u val=blah & 0x1f;
+ switch (which) {
+ case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break;
+ case 0x01:RORW(eaa,val,LoadMw,SaveMw);break;
+ case 0x02:RCLW(eaa,val,LoadMw,SaveMw);break;
+ case 0x03:RCRW(eaa,val,LoadMw,SaveMw);break;
+ case 0x04:// SHL and SAL are the same
+ case 0x06:SHLW(eaa,val,LoadMw,SaveMw);break;
+ case 0x05:SHRW(eaa,val,LoadMw,SaveMw);break;
+ case 0x07:SARW(eaa,val,LoadMw,SaveMw);break;
+ }
+ }
+ */
+ }
+ break;
+
// RETN
case 0xC3:
{
@@ -302,6 +399,27 @@ static public Instruction DecodeInstruction(uint PC, BinaryReader Reader)
};
}
break;
+ //
+ case 0xF7:
+ {
+ var Param = Reader.ReadByte();
+ var Which = (Param >> 3) & 7;
+ var Reg = (Register)((Param >> 0) & 7);
+ switch (Which)
+ {
+ /*
+ case 0: break; // TEST Ew,Iw
+ case 1: break; // TEST Ew,Iw Undocumented
+ case 2: break; // NOT Ew
+ case 3: break; // NEG Ew
+ case 4: break; // MUL AX,Ew
+ case 5: break; // IMUL AX,Ew
+ case 6: break; // DIV Ew
+ */
+ case 7: return Instruction(Opcode.IDIV, Reg); // IDIV Ew
+ default: throw (new NotImplementedException());
+ }
+ }
// GRP5 Ew
case 0xFF:
{
View
6 DotX86/DotX86/Core/Cpu/Tables/Opcode.cs
@@ -26,5 +26,11 @@ public enum Opcode
LEA,
LEAVE,
JGE,
+ CDQ,
+ IDIV,
+ TEST,
+ JZ,
+ JNZ,
+ SHL,
}
}
View
14 DotX86/DotX86/Core/Cpu/Tables/Register.cs
@@ -6,6 +6,20 @@
namespace DotX86.Core.Cpu.Tables
{
+ /*
+ public enum SRegister
+ {
+ AX = 0,
+ CX = 1,
+ DX = 2,
+ BX = 3,
+ SP = 4,
+ BP = 5,
+ SI = 6,
+ DI = 7,
+ }
+ */
+
public enum Register
{
AX = 0,
View
13 DotX86/DotX86/Core/Cpu/ThreadContext.cs
@@ -105,6 +105,19 @@ public struct FlagsStruct
public uint ESI;
public uint EDI;
+ public long EDX_EAX
+ {
+ get
+ {
+ return (long)((EDX << 32) | (EAX << 0));
+ }
+ set
+ {
+ EDX = (uint)(value >> 32);
+ EAX = (uint)(value >> 0);
+ }
+ }
+
public CpuContext CpuContext;
public Memory Memory { get { return CpuContext.Memory; } }
public Stream MemoryStream { get { return Memory.GetStream(); } }
View
1 DotX86/DotX86/DotX86.csproj
@@ -45,6 +45,7 @@
<Compile Include="Core\Cpu\Assembler\Disassembler.cs" />
<Compile Include="Core\Cpu\CpuContext.cs" />
<Compile Include="Core\Cpu\Dynarec\MethodGenerator.cs" />
+ <Compile Include="Core\Cpu\Dynarec\Operations.Comparison.cs" />
<Compile Include="Core\Cpu\Dynarec\Operations.Memory.cs" />
<Compile Include="Core\Cpu\Tables\InstructionDecoder.cs" />
<Compile Include="Core\Cpu\Tables\Instruction.cs" />
View
7 DotX86/DotX86/Hle/modules/msvcrt.cs
@@ -8,6 +8,10 @@
namespace DotX86.Hle.modules
{
+ class X86HaltException : Exception
+ {
+ }
+
public class msvcrt : module
{
public void printf(ThreadContext ThreadContext)
@@ -71,7 +75,8 @@ public void __set_app_type(ThreadContext ThreadContext)
public void exit(ThreadContext ThreadContext)
{
- //Console.ReadKey();
+ //throw (new X86HaltException());
+ Console.ReadKey();
Environment.Exit(0);
}
}
View
23 DotX86/DotX86/Program.cs
@@ -7,6 +7,7 @@
using DotX86.Core;
using DotX86.Core.Cpu;
using DotX86.Core.Cpu.Dynarec;
+using DotX86.Hle.modules;
using DotX86.Loader;
namespace DotX86
@@ -15,7 +16,7 @@ class Program
{
//static Action<int> Test;
- static void Main(string[] args)
+ static void Main2(string[] args)
{
/*
Test = (a) =>
@@ -45,6 +46,26 @@ static void Main(string[] args)
var Method = CpuContext.GetMethod(ThreadContext.PC);
Method(ThreadContext);
}
+
+ }
+
+ static void Main(string[] args)
+ {
+ try
+ {
+ Main2(args);
+ }
+ catch (X86HaltException)
+ {
+ }
+ /*
+ catch (Exception Exception)
+ {
+ Console.WriteLine(Exception);
+ }
+ */
+
+ Console.ReadKey();
//Console.WriteLine("Ended!");
//Console.ReadKey();
}

0 comments on commit 25c8765

Please sign in to comment.
Something went wrong with that request. Please try again.