public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled, _MethodInfo aMethod, ILOpCode aOpCode) { XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); XS.Comment("Size: " + aElementSize); DoNullReferenceCheck(aAssembler, debugEnabled, 8); //Do check for index out of range var xBaseLabel = GetLabel(aMethod, aOpCode); var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 XS.Compare(EAX, EBX); XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); XS.Compare(EBX, 0); XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); XS.Label(xIndexOutOfRangeExeptionLabel); XS.Pop(EAX); XS.Pop(EAX); Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); XS.Label(xNoIndexOutOfRangeExeptionLabel); XS.Push(EBX); //_, array, 0 -> _, array, 0, index // calculate element offset into array memory (including header) XS.Pop(EAX); XS.Set(EDX, aElementSize); XS.Multiply(EDX); XS.Add(EAX, (uint)(ObjectUtils.FieldDataOffset + 4)); // pop the array now XS.Add(ESP, 4); XS.Pop(EDX); XS.Add(EDX, EAX); XS.Push(EDX); }
public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) { DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4))); uint xStackSize = aElementSize; if (xStackSize % 4 != 0) { xStackSize += 4 - xStackSize % 4; } // Do index out of range check var xBaseLabel = GetLabel(aMethod, aOpCode); var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; XS.Push(ESP, displacement: 4 + 4 + (int)xStackSize); // _, array, 0, index, value * n => _, array, 0, index, value * n, array XS.Push(0); // _, array, 0, index, value * n, array => _, array, 0, index, value * n, array, 0 Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, index, value * n, array, 0 -> _, array, 0, index, value * n, length XS.Pop(EAX); //Length of array _, array, 0, index, value * n, length -> _, array, 0, index, value * n XS.Compare(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: (int)xStackSize); XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); XS.Compare(EAX, 0); XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); XS.Label(xIndexOutOfRangeExeptionLabel); Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); XS.Label(xNoIndexOutOfRangeExeptionLabel); // calculate element offset into array memory (including header) XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index XS.Set(EDX, aElementSize); XS.Multiply(EDX); XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array XS.Add(EDX, EAX); XS.Push(EDX); XS.Pop(ECX); for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1) { new Comment(aAssembler, "Start 1 dword"); XS.Pop(EBX); XS.Set(ECX, EBX, destinationIsIndirect: true); XS.Add(ECX, 4); } switch (aElementSize % 4) { case 1: { new Comment(aAssembler, "Start 1 byte"); XS.Pop(EBX); XS.Set(ECX, BL, destinationIsIndirect: true); break; } case 2: { new Comment(aAssembler, "Start 1 word"); XS.Pop(EBX); XS.Set(ECX, BX, destinationIsIndirect: true); break; } case 0: { break; } default: throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!"); } XS.Add(ESP, 12); }
public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) { // stack = index // stack + 2 = array DoNullReferenceCheck(aAssembler, debugEnabled, 8); var xBaseLabel = GetLabel(aMethod, aOpCode); var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 XS.Compare(EAX, EBX); XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); XS.Compare(EBX, 0); XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); XS.Label(xIndexOutOfRangeExeptionLabel); XS.Pop(EAX); XS.Pop(EAX); Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); XS.Label(xNoIndexOutOfRangeExeptionLabel); XS.Push(EBX); //_, array, 0 -> _, array, 0, index // calculate element offset into array memory (including header) XS.Pop(EAX); XS.Set(EDX, aElementSize); XS.Multiply(EDX); XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); if (aElementSize > 4) { // we start copying the last bytes XS.Add(EAX, aElementSize - 4); } // pop the array now XS.Add(ESP, 4); XS.Pop(EDX); XS.Add(EDX, EAX); var xSizeLeft = aElementSize; while (xSizeLeft > 0) { var xCurrentStep = Math.Min(xSizeLeft, 4); if (xSizeLeft % 4 != 0) { xCurrentStep = xSizeLeft % 4; } xSizeLeft = xSizeLeft - xCurrentStep; switch (xCurrentStep) { case 1: if (isSigned) { XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); } else { XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); } XS.Push(ECX); break; case 2: if (isSigned) { XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); } else { XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); } XS.Push(ECX); break; case 4: // copy a full dword XS.Push(EDX, true); XS.Sub(EDX, 4); // move to previous 4 bytes break; //case 8: // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true}; // XS.Push(XSRegisters.EDX, isIndirect: true); // break; } } }