public CodeExpression GetLoadExpression(InstructionForm frm)
		{
			if (Type == OperationSourceType.Constant)
			{
				return new CodePrimitiveExpression(Constant);
			}
			else
			{
				switch(frm[ParentArgIdx].ArgType.ID)
				{
					case InstructionArgType.Imm32_ID:
						return new CodeFieldReferenceExpression(
							new CodeThisReferenceExpression(),
							frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ParentArgIdx)
						);
					case InstructionArgType.Imm16_ID:
						return new CodeCastExpression(
							StaticTypeReferences.UShort,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ParentArgIdx)
							)
						);
					case InstructionArgType.Imm8_ID:
						return new CodeCastExpression(
							StaticTypeReferences.Byte,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ParentArgIdx)
							)
						);

					default:
						if (frm[ParentArgIdx].ArgType.AsArgOperation == null)
							throw new Exception("The specified arg isn't valid as an argument to a write operation!");
						return frm[ParentArgIdx].ArgType.AsArgOperation.GetExpression(frm, ParentArgIdx, null);
				}
			}
		}
		public CodeExpression GetLoadExpression(InstructionForm frm, int argIdx)
		{
			int reqFldsPrev = 0;
			foreach (var val in Parent.Parameters.Values)
			{
				if (val == this)
					break;
				if (val.ArgType == this.ArgType)
				{
					reqFldsPrev++;
				}
			}
			return new CodeFieldReferenceExpression(
				new CodeThisReferenceExpression(),
				frm.GetArgName(ArgType, reqFldsPrev + 1, argIdx)
			);
		}
		public CodeExpression GetConditionExpression(InstructionForm parent)
		{
			CodeBinaryOperatorType cond;
			switch (Condition)
			{
				case ConditionType.Less:
					cond = CodeBinaryOperatorType.LessThan;
					break;
				case ConditionType.LessOrEqual:
					cond = CodeBinaryOperatorType.LessThanOrEqual;
					break;
				case ConditionType.Greater:
					cond = CodeBinaryOperatorType.GreaterThan;
					break;
				case ConditionType.GreaterOrEqual:
					cond = CodeBinaryOperatorType.GreaterThanOrEqual;
					break;
				case ConditionType.Equal:
					cond = CodeBinaryOperatorType.ValueEquality;
					break;
				case ConditionType.NotEqual:
					cond = CodeBinaryOperatorType.IdentityInequality;
					break;
				default:
					throw new Exception("Unknown condition!");
			}
			return new CodeBinaryOperatorExpression(
				new CodeFieldReferenceExpression(
					new CodeThisReferenceExpression(),
					parent.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgToExclude)
				),
				cond,
				new CodePrimitiveExpression(ConditionArg)
			);
		}
		public void Write(CodeScopeStatement con, InstructionForm ParentForm)
		{
			switch (Type)
			{
				case WriteOperationType.Arg:
					con.Statements.Add(
						ParentForm[ArgIdx].ArgType.WriteOperation.GetExpression(ParentForm, ArgIdx, this)
					);
					break;
				case WriteOperationType.Prefix:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WritePrefix,
							new CodeFieldReferenceExpression(StaticTypeReferences.PrefixExpression, SelectedPrefix)
						)
					);
					break;
				case WriteOperationType.Byte:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteByte,
							new CodePrimitiveExpression(ByteValue)
						)
					);
					break;
				case WriteOperationType.BytePlusArg:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteByte,
							new CodeCastExpression(
								StaticTypeReferences.Byte,
								new CodeBinaryOperatorExpression(
									new CodePrimitiveExpression(ByteValue),
									CodeBinaryOperatorType.Add,
									ParentForm[ArgIdx].ArgType.AsArgOperation.GetExpression(ParentForm, ArgIdx, this)
								)
							)
						)
					);
					break;
				case WriteOperationType.Imm8:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteImm8,
							new CodeCastExpression(
								StaticTypeReferences.Byte,
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									ParentForm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIdx)
								)
							)
						)
					);
					break;
				case WriteOperationType.Imm16:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteImm16,
							new CodeCastExpression(
								StaticTypeReferences.UShort,
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									ParentForm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIdx)
								)
							)
						)
					);
					break;
				case WriteOperationType.Imm32:
					con.Statements.Add(
						new CodeMethodInvokeExpression(
							StaticTypeReferences.Emit_Stream_WriteImm32,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								ParentForm.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIdx)
							)
						)
					);
					break;
				case WriteOperationType.Throw:
					con.Statements.Add(
						new CodeThrowExceptionStatement(
							new CodeObjectCreateExpression(
								StaticTypeReferences.Exception,
								new CodePrimitiveExpression(MessageThrown)
							)
						)
					);
					break;
				default:
					throw new Exception("Unsupported write operation type!");
			}
		}
			public CodeExpression GetConditionExpression(InExactInstructionOverrideDescription ParentDesc, InstructionForm formOverriding)
			{
				switch (Condition)
				{
					case ConditionType.Fits:
						switch(ParentDesc.NewForm[ArgIndexToCheck].ArgType.ID)
						{
							case InstructionArgType.Dis8_ID:
							case InstructionArgType.Imm8_ID:
								return new CodeMethodInvokeExpression(
									StaticTypeReferences.Stream_InSByteRange,
									new CodeCastExpression(
										StaticTypeReferences.Int,
										new CodeFieldReferenceExpression(
											new CodeThisReferenceExpression(),
											formOverriding.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIndexToCheck)
										)
									)
								);
							case InstructionArgType.Dis16_ID:
							case InstructionArgType.Imm16_ID:
								return new CodeMethodInvokeExpression(
									StaticTypeReferences.Stream_InShortRange,
									new CodeCastExpression(
										StaticTypeReferences.Int,
										new CodeFieldReferenceExpression(
											new CodeThisReferenceExpression(),
											formOverriding.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIndexToCheck)
										)
									)
								);

							default:
								throw new Exception("Unknown arg type!");
						}
					case ConditionType.Compare_Imm:
						if (ParentDesc.NewForm[ArgIndexToCheck].ArgType == InstructionArgType.Imm8)
						{
							return new CodeBinaryOperatorExpression(
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									formOverriding.GetArgName(FieldTypeRegistry.UInt.ID, 1, ArgIndexToCheck)
								),
								CodeBinaryOperatorType.ValueEquality,
								new CodePrimitiveExpression(ImmValueToCompareTo)
							);
						}
						else
						{
							return new CodeBinaryOperatorExpression(
								ParentDesc.NewForm[ArgIndexToCheck].ArgType.AsArgOperation.GetExpression(ParentDesc.NewForm, ArgIndexToCheck, null),
								CodeBinaryOperatorType.ValueEquality,
								new CodePrimitiveExpression(ImmValueToCompareTo)
							);
						}
					case ConditionType.Compare_Reg:
						// Yikes....
						var enu = formOverriding[ArgIndexToCheck].ArgType.Parameters.Values.GetEnumerator();
						enu.MoveNext();
						int argType = enu.Current.ArgType;
						return new CodeBinaryOperatorExpression(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								formOverriding.GetArgName(argType, 1, ArgIndexToCheck)
							),
							CodeBinaryOperatorType.ValueEquality,
							new CodeFieldReferenceExpression(
								new CodeTypeReferenceExpression(FieldTypeRegistry.Fields[argType].Name),
								RegisterToCompareTo
							)
						);
					case ConditionType.Compare_Segment:
						return new CodeBinaryOperatorExpression(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								formOverriding.GetArgName(FieldTypeRegistry.Segment.ID, 1, ArgIndexToCheck)
							),
							CodeBinaryOperatorType.ValueEquality,
							new CodeFieldReferenceExpression(StaticTypeReferences.SegmentExpression, RegisterToCompareTo)
						);
					default:
						throw new Exception("Unknown Condition!");
				}
			}
		public void WriteConditionalEmit(CodeScopeStatement con, InstructionForm overridenForm, bool ignoreOtherOverrides = false)
		{
			if (Conditions.Count == 0)
				throw new Exception("There are no conditions to the override!");
			if (!ignoreOtherOverrides && CanGenSegmentSwitch(overridenForm))
			{
				CodeSwitchStatement sw = new CodeSwitchStatement(
					new CodeFieldReferenceExpression(
						new CodeThisReferenceExpression(),
						overridenForm.GetArgName(FieldTypeRegistry.Segment.ID, 1, Conditions[0].ArgIndexToCheck)
					)
				);
				for (int i = 0; i < overridenForm.Overrides.Count; i++)
				{
					CodeCaseStatement cs = new CodeCaseStatement(
						new CodeFieldReferenceExpression(
							StaticTypeReferences.SegmentExpression,
							overridenForm.Overrides[i].Conditions[0].RegisterToCompareTo
						)
					);
					CodeScopeStatement cst = new CodeScopeStatement();
					overridenForm.Overrides[i].NewForm.WriteEmit(cst, true);
					cst.Statements.Add(new CodeBreakStatement());
					cs.Statements.Add(cst);
					sw.Cases.Add(cs);
				}
				CodeDefaultCaseStatement defStat = new CodeDefaultCaseStatement();
				CodeScopeStatement defCont = new CodeScopeStatement();
				overridenForm.WriteEmit(defCont, true);
				defStat.Statements.Add(defCont);
				if (overridenForm.WriteOperations[0].Type != WriteOperationType.Throw)
				{
					defStat.Statements.Add(new CodeBreakStatement());
				}
				sw.Cases.Add(defStat);
				con.Statements.Add(sw);
			}
			else
			{
				CodeScopeStatement tCont = new CodeScopeStatement();
				CodeScopeStatement fCont = new CodeScopeStatement();
				CodeExpression condition = Conditions[0].GetConditionExpression(this, overridenForm);
				for (int i = 1; i < Conditions.Count; i++)
				{
					condition = new CodeBinaryOperatorExpression(
						condition, 
						CodeBinaryOperatorType.BooleanAnd, 
						Conditions[i].GetConditionExpression(this, overridenForm)
					);
				}
				CodeConditionStatement condStat = new CodeConditionStatement(condition, new CodeStatement[] { tCont });
				NewForm.WriteEmit(tCont, true);
				if (!ignoreOtherOverrides)
				{
					condStat.FalseStatements.Add(fCont);
					if (overridenForm.Overrides.Count > 1)
					{
						// If we've gotten here, we know that we are the override at index 0.
						for (int i = 1; i < overridenForm.Overrides.Count; i++)
						{
							CodeScopeStatement eICont = new CodeScopeStatement();
							overridenForm.Overrides[i].WriteConditionalEmit(eICont, overridenForm, true);
							fCont.Statements.Add(eICont);
							fCont = new CodeScopeStatement();
							((CodeConditionStatement)eICont.Statements[0]).FalseStatements.Add(fCont);
						}
					}
					overridenForm.WriteEmit(fCont, true);
				}
				con.Statements.Add(condStat);
			}
		}
		public CodeExpression GetToStringForArg(InstructionForm frm, int argIdx)
		{
			InstructionArg arg = frm[argIdx];
			int padSize = 0;
			switch (arg.ArgType.ID)
			{
				case InstructionArgType.Dis8_ID:
				case InstructionArgType.Dis16_ID:
				case InstructionArgType.Dis32_ID:
					return new CodeMethodInvokeExpression(
						StaticTypeReferences.NamingHelper_NameDisplacement,
						StaticTypeReferences.ParentAssemblerExpression,
						new CodeThisReferenceExpression(),
						new CodeCastExpression(
							StaticTypeReferences.Int,
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							)
						)
					);

				case InstructionArgType.Imm8_ID:
					padSize = 2;
					goto ImmCommon;
				case InstructionArgType.Imm16_ID:
					padSize = 4;
					goto ImmCommon;
				case InstructionArgType.Imm32_ID:
					padSize = 8;
					goto ImmCommon;
				default:
					return arg.ArgType.ReadOperation.GetExpression(frm, argIdx, null);
			}
		ImmCommon:
			if (arg.NumberFormat == ImmNumberFormat.Decimal)
			{
				return new CodeMethodInvokeExpression(
					new CodeFieldReferenceExpression(
						new CodeThisReferenceExpression(),
						frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
					),
					"ToString"
				);
			}
			else
			{
				return Generator.LanguageProvider.GetPaddedHexToString(
					new CodeFieldReferenceExpression(
						new CodeThisReferenceExpression(),
						frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
					),
					padSize
				);
			}
		}
		public void WriteConstructorBodyArgProcessing(InstructionForm frm, CodeConstructor c, int argIdx)
		{
			InstructionArg arg = frm[argIdx];
			switch (ID)
			{
				case None_ID:
					break;
				// Dis8 & Dis16 have to be sign-extended before being stored.
				// (this way they can be compared using the exact same code as
				// dis32 can)
				case Dis8_ID:
				case Dis16_ID:
					c.Statements.Add(
						new CodeAssignStatement(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							),
							new CodeCastExpression(
								StaticTypeReferences.UInt,
								new CodeCastExpression(
									StaticTypeReferences.Int,
									new CodeArgumentReferenceExpression(arg.Name + DisArgSuffix)
								)
							)
						)
					);
					break;
				// No sign extension needed.
				case Dis32_ID:
					c.Statements.Add(
						new CodeAssignStatement(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							),
							new CodeCastExpression(
								StaticTypeReferences.UInt,
								new CodeArgumentReferenceExpression(arg.Name + DisArgSuffix)
							)
						)
					);
					break;
				case Imm8_ID:
				case Imm16_ID:
				case Imm32_ID:
					c.Statements.Add(
						new CodeAssignStatement(
							new CodeFieldReferenceExpression(
								new CodeThisReferenceExpression(),
								frm.GetArgName(FieldTypeRegistry.UInt.ID, 1, argIdx)
							),
							new CodeCastExpression(
								StaticTypeReferences.UInt,
								new CodeArgumentReferenceExpression(arg.Name + ImmArgSuffix)
							)
						)
					);
					break;

				default:
					int[] reqs = new int[FieldTypeRegistry.MaxFieldID + 1];
					foreach(CustomInstructionArgParameter p in mParameters.Values)
					{
						c.Statements.Add(
							new CodeAssignStatement(
								new CodeFieldReferenceExpression(
									new CodeThisReferenceExpression(),
									frm.GetArgName(p.ArgType, reqs[p.ArgType] + 1, argIdx)
								),
								new CodeArgumentReferenceExpression(arg.Name + p.ArgNameSuffix)
							)
						);
						reqs[p.ArgType]++;
					}
					break;
			}
		}
		private CodeExpression GetExpressionFromIdentifier(string val, InstructionForm frm, int argIdx, WriteOperation wrOp, bool namedParamNeedsCast = false)
		{
			CustomInstructionArgParameter param;
			if (ParentArg.Parameters.TryGetValue(val, out param))
			{
				if (namedParamNeedsCast)
				{
					return frm[argIdx].ArgType.AsArgOperation.GetExpression(frm, argIdx, wrOp);
				}
				else
				{
					return param.GetLoadExpression(frm, argIdx);
				}
			}
			else if (val == "Segment")
			{
				return new CodeFieldReferenceExpression(
					new CodeThisReferenceExpression(),
					frm.GetArgName(FieldTypeRegistry.Segment.ID, 1, InstructionArgSet.TotalArgs_Max)
				);
			}
			else if (val == "ParentAssembler")
			{
				return StaticTypeReferences.ParentAssemblerExpression;
			}
			else if (val == "Stream")
			{
				return StaticTypeReferences.Emit_StreamArg;
			}
			else if (val.StartsWith("arg"))
			{
				int fArg = Utils.SingleDigitParse(val[3]) - 1;
				return wrOp.WriteArguments[fArg].GetLoadExpression(frm);
			}
			else
			{
				return new CodeTypeReferenceExpression(val);
			}
		}