Cosmos
Cosmos copied to clipboard
Either 'bitshift' or 'bitwise or' operators cause the kernel to lock up
Area of Cosmos - What area of Cosmos are we dealing with?
Unknown, could be il2cpu
Expected Behaviour - What do you think that should happen?
The operations should complete successfully - Tested working outside of cosmos
Actual Behaviour - What unexpectedly happens?
The entire kernel locks up and nothing can be done
Reproduction - How did you get this error to appear?
byte A = 255;
byte R = 255;
byte G = 255;
byte B = 255;
uint Result = (uint)(A << 24 | R << 16 | G << 8 | B);
Console.WriteLine(Result);
Version - Were you using the User Kit or Dev Kit? And what User Kit version or Dev Kit commit (Cosmos, IL2CPU, X#)?
Latest
mmm so i was not going insane
public static bool HasFlag(ref Int32 data, int flagOffset)
{
if (flagOffset is < 0 or > 31) throw new ArgumentOutOfRangeException("flagOffset");
var flag = data >> flagOffset;
return (flag & 1) == 1;
}
i think it might be this that that is locking up my CPUID code
That's interesting... Cosmos uses bit-shifts all over the code base internally. Can you post a snippet of the Assembly code it generated that corresponds to the shr
IL op-code? You can try using QEMU to see at which address it hangs and locate the appropriate IL op-code label with the map file.
As a work-around, you can try using unchecked((uint)(A * 16777216u + R * 65536u + G * 256u + B));
. This is equivalent to the bit-shifts and bitwise operations (but would perform worse on x86).
idk but something's a bit odd there
public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode )
{
var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0];
var xStackItem_Value = aOpCode.StackPopTypes[1];
var xStackItem_Value_Size = SizeOfType(xStackItem_Value);
XS.Pop(XSRegisters.ECX); // shift amount
#if DOTNETCOMPATIBLE
if (xStackItem_Value.Size == 4)
#else
if (xStackItem_Value_Size <= 4)
#endif
{
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
//XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
XS.ShiftRightArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
}
#if DOTNETCOMPATIBLE
else if (xStackItem_Value_Size == 8)
#else
else if (xStackItem_Value_Size <= 8)
#endif
{
string BaseLabel = GetLabel(aMethod, aOpCode) + ".";
string HighPartIsZero = BaseLabel + "HighPartIsZero";
string End_Shr = BaseLabel + "End_Shr";
// [ESP] is low part
// [ESP + 4] is high part
// move high part in EAX
XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);
XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8);
XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero);
// shift lower part
XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true);
// shift higher part
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
//XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
XS.Jump(End_Shr);
XS.Label(HighPartIsZero);
// remove bits >= 32, so that CL max value could be only 31
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
// shift high part and move it in low part
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL);
XS.Set(ESP, EAX, destinationIsIndirect: true);
// replace unknown high part with a zero
XS.Set(ESP, 0, destinationIsIndirect: true, destinationDisplacement: 4);
//new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
XS.Label(End_Shr);
}
else
throw new NotSupportedException("A size bigger 8 not supported at Shr!");
/*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode);
var xStackItem_ShiftAmount = Assembler.Stack.Pop();
var xStackItem_Value = Assembler.Stack.Peek();
if( xStackItem_Value.Size <= 4 )
{
XS.Pop(XSRegisters.ECX); // shift amount
XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true);
}
else if( xStackItem_Value.Size <= 8 )
{
XS.Pop(XSRegisters.ECX); // shift amount
// [ESP] is high part
// [ESP + 4] is low part
XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4);
// shift low part
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL };
// shift high part
XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
}*/
}
}
unchecked((uint)(A * 16777216u + R * 65536u + G * 256u + B));
That code works for now, thanks.
I'm already working with quajak on this
idk but something's a bit odd there
public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) { var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; var xStackItem_Value = aOpCode.StackPopTypes[1]; var xStackItem_Value_Size = SizeOfType(xStackItem_Value); XS.Pop(XSRegisters.ECX); // shift amount #if DOTNETCOMPATIBLE if (xStackItem_Value.Size == 4) #else if (xStackItem_Value_Size <= 4) #endif { // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! //XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); XS.ShiftRightArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); } #if DOTNETCOMPATIBLE else if (xStackItem_Value_Size == 8) #else else if (xStackItem_Value_Size <= 8) #endif { string BaseLabel = GetLabel(aMethod, aOpCode) + "."; string HighPartIsZero = BaseLabel + "HighPartIsZero"; string End_Shr = BaseLabel + "End_Shr"; // [ESP] is low part // [ESP + 4] is high part // move high part in EAX XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); // shift lower part XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); // shift higher part // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! //XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); XS.Jump(End_Shr); XS.Label(HighPartIsZero); // remove bits >= 32, so that CL max value could be only 31 XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); // shift high part and move it in low part // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL); XS.Set(ESP, EAX, destinationIsIndirect: true); // replace unknown high part with a zero XS.Set(ESP, 0, destinationIsIndirect: true, destinationDisplacement: 4); //new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0}; XS.Label(End_Shr); } else throw new NotSupportedException("A size bigger 8 not supported at Shr!"); /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode); var xStackItem_ShiftAmount = Assembler.Stack.Pop(); var xStackItem_Value = Assembler.Stack.Peek(); if( xStackItem_Value.Size <= 4 ) { XS.Pop(XSRegisters.ECX); // shift amount XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true); } else if( xStackItem_Value.Size <= 8 ) { XS.Pop(XSRegisters.ECX); // shift amount // [ESP] is high part // [ESP + 4] is low part XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); // shift low part new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL }; // shift high part XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); }*/ } }
Where is this code located?
at is was this line public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode )
before then it was like 6 years