static private IList <byte> generateOffset(AssemblyOperand operand, EnumOffsetType offsetType, out bool calleeSuccess) { IList <byte> result = new List <byte>(); uint rm; calleeSuccess = false; if (operand.type == AssemblyOperand.EnumType.MEMORYSIMPLE) { if (offsetType == EnumOffsetType.NOOFFSET) { result = new List <byte>(); } else if (offsetType == EnumOffsetType.SINGLEBYTE) { result = new List <byte>() { (byte)operand.offset }; } else if (offsetType == EnumOffsetType.FOURBYTES) { /* commented because not translated from D * ubyte *pointerToOffset; * * pointerToOffset = cast(ubyte*)&operand.offset; * * result = [pointerToOffset[0], pointerToOffset[1], pointerToOffset[2], pointerToOffset[3]]; * * assert(false, "TODO"); */ throw new NotImplementedException("TODO"); } calleeSuccess = true; return(result); } else if (operand.type == AssemblyOperand.EnumType.XMM || operand.type == AssemblyOperand.EnumType.GENERALREGISTER) { // we dont need any offset for an xmm or a general register calleeSuccess = true; return(new List <byte>()); } else { return(new List <byte>()); } throw new Exception("Unreachable!"); }
static private byte generateRmByteAndGetOffsetType(AssemblyOperand operandLeft, int defaultReg, AssemblyOperand operandRight, bool in64BitMode, out EnumOffsetType offsetType, out bool calleeSuccess) { uint registerMaxIndex; uint reg, mod, rm; offsetType = EnumOffsetType.NOOFFSET; calleeSuccess = false; if (in64BitMode) { registerMaxIndex = 16; } else { registerMaxIndex = 8; } if (defaultReg == -1) { if (operandLeft.type == AssemblyOperand.EnumType.XMM && operandLeft.xmmRegister <= registerMaxIndex) { reg = operandLeft.xmmRegister; } else if (operandLeft.type == AssemblyOperand.EnumType.GENERALREGISTER && operandLeft.generalPurposeRegister <= registerMaxIndex) { reg = operandLeft.generalPurposeRegister; } else { return(0); } } else { Debug.Assert(defaultReg >= 0); reg = (uint)defaultReg; } if (operandRight.type == AssemblyOperand.EnumType.XMM) { if (operandRight.xmmRegister >= registerMaxIndex) { return(0); } mod = 3; rm = operandRight.xmmRegister; } else if (operandRight.type == AssemblyOperand.EnumType.GENERALREGISTER) { if (operandRight.generalPurposeRegister >= registerMaxIndex) { return(0); } mod = 3; rm = operandRight.generalPurposeRegister; } else if (operandRight.type == AssemblyOperand.EnumType.MEMORYSIMPLE) { if (operandRight.offset == 0) { offsetType = EnumOffsetType.NOOFFSET; } else if (operandRight.offset <= 127 && operandRight.offset >= -128) { offsetType = EnumOffsetType.SINGLEBYTE; } else { offsetType = EnumOffsetType.FOURBYTES; } // TODO< force offset with hints if possible > if (offsetType == EnumOffsetType.NOOFFSET) { mod = 0; } else if (offsetType == EnumOffsetType.SINGLEBYTE) { mod = 1; } else if (offsetType == EnumOffsetType.FOURBYTES) { mod = 2; } else { throw new Exception("Unreachable!"); } if (operandRight.register == AssemblyOperand.EnumRegister.EAX) { rm = 0; } else if (operandRight.register == AssemblyOperand.EnumRegister.EBX) { rm = 3; } else if (operandRight.register == AssemblyOperand.EnumRegister.ECX) { rm = 1; } else if (operandRight.register == AssemblyOperand.EnumRegister.EDX) { rm = 2; } else { // possible todo or unimplemented throw new Exception("Internal error!"); } } else { // unimplemented, todo, internal error throw new Exception("Internal error!"); } calleeSuccess = true; return((byte)(((mod & 3) << 6) | ((reg & 7) << 3) | (rm & 7))); }