/// <summary> /// Writes an instruction's opcode /// </summary> /// <param name="writer">The instruction writer</param> /// <param name="instr">The instruction</param> protected void WriteOpCode(ref ArrayWriter writer, Instruction instr) { var code = instr.OpCode.Code; var hi = (ushort)code >> 8; if ((ushort)code <= 0xFF) { writer.WriteByte((byte)code); } else if (hi == 0xFE || (hi >= 0xF0 && hi <= 0xFB)) { writer.WriteByte((byte)((ushort)code >> 8)); writer.WriteByte((byte)code); } else if (code == Code.UNKNOWN1) { writer.WriteByte((byte)Code.Nop); } else if (code == Code.UNKNOWN2) { writer.WriteUInt16((ushort)(((ushort)Code.Nop << 8) | Code.Nop)); } else { Error("Unknown instruction"); writer.WriteByte((byte)Code.Nop); } }
/// <summary> /// Writes an <see cref="OperandType.InlineVar"/> operand /// </summary> /// <param name="writer">Instruction writer</param> /// <param name="instr">Instruction</param> protected virtual void WriteInlineVar(ref ArrayWriter writer, Instruction instr) { var variable = instr.Operand as IVariable; if (variable is null) { Error("Operand is not a local/arg"); writer.WriteUInt16(0); } else { int index = variable.Index; if (ushort.MinValue <= index && index <= ushort.MaxValue) { writer.WriteUInt16((ushort)index); } else { Error("Local/arg index doesn't fit in a UInt16"); writer.WriteUInt16(0); } } }