public static Type GetObjType(KnownObjectTypes objt) { switch (objt) { case KnownObjectTypes.Boolean: return(typeof(bool)); case KnownObjectTypes.Byte: return(typeof(byte)); case KnownObjectTypes.SByte: return(typeof(sbyte)); case KnownObjectTypes.Short: return(typeof(short)); case KnownObjectTypes.UShort: return(typeof(ushort)); case KnownObjectTypes.Int: return(typeof(int)); case KnownObjectTypes.UInt: return(typeof(uint)); case KnownObjectTypes.Long: return(typeof(long)); case KnownObjectTypes.ULong: return(typeof(ulong)); case KnownObjectTypes.Float: return(typeof(float)); case KnownObjectTypes.Double: return(typeof(double)); case KnownObjectTypes.String: return(typeof(string)); default: throw new Exception("Unexpected type: " + objt.ToString()); } }
public static Type GetObjType(KnownObjectTypes objt) { switch (objt) { case KnownObjectTypes.Boolean: return typeof(bool); case KnownObjectTypes.Byte: return typeof(byte); case KnownObjectTypes.SByte: return typeof(sbyte); case KnownObjectTypes.Short: return typeof(short); case KnownObjectTypes.UShort: return typeof(ushort); case KnownObjectTypes.Int: return typeof(int); case KnownObjectTypes.UInt: return typeof(uint); case KnownObjectTypes.Long: return typeof(long); case KnownObjectTypes.ULong: return typeof(ulong); case KnownObjectTypes.Float: return typeof(float); case KnownObjectTypes.Double: return typeof(double); case KnownObjectTypes.String: return typeof(string); default: throw new Exception("Unexpected type: " + objt.ToString()); } }
public void Ldelem_common(InstructionElement el) { VirtualRegister elementIndex = PopStack(_RTMP0); VirtualRegister arrayPointer = PopStack(_RTMP1); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; if (el.Childnodes[1].StorageClass != typeof(int)) throw new Exception("Unexpected index type: " + el.Childnodes[1].StorageClass.ToString()); KnownObjectTypes[] arraytypes; switch (el.Instruction.OpCode.Code) { case Mono.Cecil.Cil.Code.Ldelem_I1: //case Mono.Cecil.Cil.Code.Ldelem_Bool: //Does not exist arraytypes = new KnownObjectTypes[] { KnownObjectTypes.SByte, KnownObjectTypes.Boolean }; break; case Mono.Cecil.Cil.Code.Ldelem_I2: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Short }; break; case Mono.Cecil.Cil.Code.Ldelem_I4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Int }; break; case Mono.Cecil.Cil.Code.Ldelem_I8: //case Mono.Cecil.Cil.Code.Ldelem_U8: //Does not exist arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Long, KnownObjectTypes.ULong }; break; case Mono.Cecil.Cil.Code.Ldelem_R4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Float }; break; case Mono.Cecil.Cil.Code.Ldelem_R8: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Double }; break; case Mono.Cecil.Cil.Code.Ldelem_U1: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Byte }; break; case Mono.Cecil.Cil.Code.Ldelem_U2: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.UShort }; break; case Mono.Cecil.Cil.Code.Ldelem_U4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.UInt }; break; default: throw new Exception("Unsupport array type: " + el.Instruction.OpCode.Code); } LoadElementAddress(el, arraytypes, (uint)elementIndex.RegisterNumber, (uint)arrayPointer.RegisterNumber, _RTMP0); LoadElement(arraytypes[0], _RTMP0, (uint)o.RegisterNumber); PushStack(o); }
/// <summary> /// Stores the given value as an array element at the position indicated by the pointer. /// Note that this function is expected to be the last in the sequence and /// destroys all temporary registers. /// Note that no type/index checks are performed. /// </summary> /// <param name="arraytype">The type of the array elements</param> /// <param name="pointer">The register that contains the element address must not be _RTMP0, _RTMP2, _RTMP3</param> /// <param name="value">The register that contains the value to store, must not be _RTMP1, _RTMP2, _RTMP3</param> private void StoreElement(KnownObjectTypes arraytype, uint pointer, uint value) { System.Diagnostics.Debug.Assert(pointer != _RTMP0 && pointer != _RTMP2 && pointer != _RTMP3); System.Diagnostics.Debug.Assert(value != _RTMP1 && value != _RTMP2 && value != _RTMP3); uint eldivsize = BuiltInSPEMethods.get_array_elem_len_mult((uint)arraytype); //Calculate the number of bytes to shift left, i.e. 16 - bytes_shift_right m_state.Instructions.Add(new SPEEmulator.OpCodes.sfi(_RTMP2, pointer, 0x10)); //16 - value //The instruction ignores anything but the low four bits anyway //m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP2, (uint)pointer.RegisterNumber, 0xfu)); //Remove anything but the low 4 bits uint mask; if (eldivsize == 0) mask = 0x8000; else if (eldivsize == 1) mask = 0xC000; else if (eldivsize == 2) mask = 0xf000; else if (eldivsize == 3) mask = 0xff00; else throw new InvalidProgramException(); //Get a mask for selecting the element from the source, and rotate it into place m_state.Instructions.Add(new SPEEmulator.OpCodes.fsmbi(_RTMP3, mask)); //Get mask m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP3, _RTMP3, _RTMP2)); //Rotate into place //Place the new value in the slot if (eldivsize == 0) { m_state.Instructions.Add(new SPEEmulator.OpCodes.sfi(_RTMP2, pointer, 0x03)); //3 - Pointer m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP2, _RTMP2, 0x03)); //Only low 2 bits m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP0, value, _RTMP2)); //Rotate into place m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP0, _RTMP0, _RTMP3)); //Select the portion of the value } else if (eldivsize == 1) { m_state.Instructions.Add(new SPEEmulator.OpCodes.sfi(_RTMP2, pointer, 0x02)); //2 - Pointer m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP2, _RTMP2, 0x02)); //Only bit at pos 1 m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP0, value, _RTMP2)); //Rotate into place m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP0, _RTMP0, _RTMP3)); //Select the portion of the value } else { m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP0, value, _RTMP3)); //Select the portion of the value } //Remove the current value in the slot m_state.Instructions.Add(new SPEEmulator.OpCodes.xori(_RTMP3, _RTMP3, 0x3ff)); //Invert mask m_state.Instructions.Add(new SPEEmulator.OpCodes.lqd(_RTMP2, pointer, 0x0)); //Load current m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP2, _RTMP2, _RTMP3)); //Mask out slot m_state.Instructions.Add(new SPEEmulator.OpCodes.or(_RTMP0, _RTMP0, _RTMP2)); //Merge the two values //Save the value in LS m_state.Instructions.Add(new SPEEmulator.OpCodes.stqd(_RTMP0, pointer, 0)); }
/// <summary> /// Function that loads an array element from an address and places it on the stack. /// Note that this function is expected to be the last in a sequence and as /// such destroys all temporary registers. /// Note that this function does no type/index checking. /// </summary> /// <param name="arraytype">The array element type</param> /// <param name="pointer">The register that holds the address, cannot be _RTMP3</param> /// <param name="output">The register to receive the loaded value</param> private void LoadElement(KnownObjectTypes arraytype, uint pointer, uint output) { //We overwrite this register early on System.Diagnostics.Debug.Assert(pointer != _RTMP3); //Load the value m_state.Instructions.Add(new SPEEmulator.OpCodes.lqd(_RTMP3, pointer, 0)); //Figure out how much non-aligned we are m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP1, pointer, 0xfu)); //Use only the lower bits m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP3, _RTMP3, _RTMP1)); //Rotate into prefered slot ExpandValue(arraytype, _RTMP3, output); }
/// <summary> /// Function that expands the value in a register to fit onto the stack. /// Note that this function is expected to be the last in a sequence and as /// such destroys all temporary registers. /// </summary> /// <param name="type">The element type</param> /// <param name="valueRegister">The register that holds the value</param> /// <param name="outputregister">The register into which the expanded value is stored</param> private void ExpandValue(KnownObjectTypes type, uint valueRegister, uint outputregister) { uint eldivsize = BuiltInSPEMethods.get_array_elem_len_mult((uint)type); bool signed = type == KnownObjectTypes.SByte || type == KnownObjectTypes.Short || type == KnownObjectTypes.Int || type == KnownObjectTypes.Long; uint tmpReg = valueRegister == _RTMP0 ? _RTMP1 : _RTMP0; if (signed) { ulong mask; if (eldivsize == 0) mask = 0x1010101010101010; else if (eldivsize == 1) mask = 0x1011101110111011; else if (eldivsize == 2) mask = 0x1011121310111213; else if (eldivsize == 3) mask = 0x1011121314151617; else throw new InvalidProgramException(); //Load the new value into the register m_state.RegisterConstantLoad(mask, mask); //Load element into register m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(tmpReg, 0)); m_state.Instructions.Add(new SPEEmulator.OpCodes.shufb(outputregister, valueRegister, valueRegister, tmpReg)); //Move word into position (should be 4 bytes) //Since the element must be stored as int32 on stack, we must convert it and sign extend it if (eldivsize <= 0) m_state.Instructions.Add(new SPEEmulator.OpCodes.xsbh(outputregister, outputregister)); //Convert to halfword if (eldivsize <= 1) m_state.Instructions.Add(new SPEEmulator.OpCodes.xshw(outputregister, outputregister)); //Convert to word } else { ulong mask; if (eldivsize == 0) mask = 0x8080801080808010; else if (eldivsize == 1) mask = 0x8080101180801011; else if (eldivsize == 2) mask = 0x1011121310111213; else if (eldivsize == 3) mask = 0x1011121314151617; else throw new InvalidProgramException(); //Load the new value into the register m_state.RegisterConstantLoad(mask, mask); //Load element into register m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(tmpReg, 0)); m_state.Instructions.Add(new SPEEmulator.OpCodes.shufb(outputregister, valueRegister, valueRegister, tmpReg)); //Move word into position (should be 4 bytes) } }
public void Stelem_common(InstructionElement el) { VirtualRegister value = PopStack(_RTMP4); VirtualRegister elementIndex = PopStack(_RTMP0); VirtualRegister arrayPointer = PopStack(_RTMP1); KnownObjectTypes[] arraytypes; switch (el.Instruction.OpCode.Code) { case Mono.Cecil.Cil.Code.Stelem_I: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Int }; break; case Mono.Cecil.Cil.Code.Stelem_I1: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.SByte, KnownObjectTypes.Boolean, KnownObjectTypes.Byte }; break; case Mono.Cecil.Cil.Code.Stelem_I2: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Short, KnownObjectTypes.UShort }; break; case Mono.Cecil.Cil.Code.Stelem_I4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Int, KnownObjectTypes.UInt }; break; case Mono.Cecil.Cil.Code.Stelem_I8: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Long, KnownObjectTypes.ULong }; break; case Mono.Cecil.Cil.Code.Stelem_R4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Float }; break; case Mono.Cecil.Cil.Code.Stelem_R8: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Double }; break; case Mono.Cecil.Cil.Code.Stelem_Ref: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Object }; break; default: throw new Exception("Unsupported stelem instruction: " + el.Instruction.OpCode.Code); } LoadElementAddress(el, arraytypes, (uint)elementIndex.RegisterNumber, (uint)arrayPointer.RegisterNumber, _RTMP1); StoreElement(arraytypes[0], _RTMP1, (uint)value.RegisterNumber); }