/// <summary> /// Creates a new instance of a ZInstruction. Check the complete table of opcodes for valid values. /// </summary> /// <param name="name">The Inform name for the used opcode. It is used for debugging purposes only, so you COULD leave this empty or null.</param> /// <param name="opcodeNumer">The opcode number.</param> /// <param name="opcodeType">The opcode type.</param> /// <param name="operands">The operands to use.</param> public ZInstruction(string name, byte opcodeNumber, OpcodeTypeKind opcodeType, params ZOperand[] operands) { var result = OpcodeHelper.GetFormAndCount(opcodeNumber, opcodeType, operands); _opcode = new ZOpcode(name, opcodeNumber, result.Item1, result.Item2, operands.Select(o => o.OperandType).ToArray()); _subComponents.Add(_opcode); _operands = operands; _subComponents.AddRange(operands); }
/// <summary> /// Creates a new instance of a ZInstructionSt. Check the complete table of opcodes for valid values. /// </summary> /// <param name="name">The Inform name for the used opcode. It is used for debugging purposes only, so you COULD leave this empty or null.</param> /// <param name="opcodeNumer">The opcode number.</param> /// <param name="opcodeType">The opcode type.</param> /// <param name="store">The store variable.</param> /// <param name="operands">The operands to use.</param> public ZInstructionSt(string name, byte opcodeNumber, OpcodeTypeKind opcodeType, ZVariable store, params ZOperand[] operands) : base(name, opcodeNumber, opcodeType, operands) { _store = store; _subComponents.Add(store); }
/// <summary> /// Takes several opcode information and returns the best match of InstructionFormKind and InstructionOperandCountKind. /// </summary> /// <param name="opcodeNumber">The opcode number.</param> /// <param name="opcodeType">The opcode type as written in the table of opcodes.</param> /// <param name="operands">The operands to use.</param> /// <returns>A tuple of InstructionFormKind and InstructionOperandCountKind.</returns> /// <exception cref="ArgumentOutOfRangeException"> If <paramref name="opcodeNumber"/> has an invalid value or <paramref name="operands"/> an invalid count of operands.</exception> /// <exception cref="ArgumentException"> If <paramref name="operands"/> contains an unknown enum value.</exception> public static Tuple<InstructionFormKind, InstructionOperandCountKind> GetFormAndCount(byte opcodeNumber, OpcodeTypeKind opcodeType, ZOperand[] operands) { InstructionFormKind instructionForm; InstructionOperandCountKind operandCount; if (opcodeType == OpcodeTypeKind.ZeroOP) { if (opcodeNumber > 0xF) throw new ArgumentOutOfRangeException("opcodeNumber", opcodeNumber, "The opcode number of an OpcodeTypeKind.ZeroOP must be in range of 0x0 - 0xF."); if (operands.Count() > 0) throw new ArgumentOutOfRangeException("operands", operands.Count(), "With OpcodeTypeKind.ZeroOP no operands must be given."); instructionForm = InstructionFormKind.Short; operandCount = InstructionOperandCountKind.ZeroOP; } else if (opcodeType == OpcodeTypeKind.OneOP) { if (opcodeNumber > 0xF) throw new ArgumentOutOfRangeException("opcodeNumber", opcodeNumber, "The opcode number of an OpcodeTypeKind.OneOP must be in range of 0x0 - 0xF."); if (operands.Count() != 1) throw new ArgumentOutOfRangeException("operands", operands.Count(), "With OpcodeTypeKind.OneOP excactly operands must be given."); instructionForm = InstructionFormKind.Short; operandCount = InstructionOperandCountKind.OneOP; } else if (opcodeType == OpcodeTypeKind.TwoOP) { if (opcodeNumber > 0x1F) throw new ArgumentOutOfRangeException("opcodeNumber", opcodeNumber, "The opcode number of an OpcodeTypeKind.TwoOP must be in range of 0x00 - 0x1F."); if (operands.Count() != 2) throw new ArgumentOutOfRangeException("operands", operands.Count(), "With OpcodeTypeKind.TwoOP exactly two operands must be given."); // Could be in long form for two small constants or variables // But let's keep this logic dumb // We could save 1 byte per OpcodeTypeKind.TwoOP at best instructionForm = InstructionFormKind.Variable; operandCount = InstructionOperandCountKind.TwoOP; } else if (opcodeType == OpcodeTypeKind.Var) { if (opcodeNumber > 0x1F) throw new ArgumentOutOfRangeException("opcodeNumber", opcodeNumber, "The opcode number of an OpcodeTypeKind.Var must be in range of 0x00-0x1F."); if (operands.Count() > 4) { if (operands.Count() <= 8) throw new ArgumentOutOfRangeException("operands", operands.Count(), "With OpcodeTypeKind.Var only 0 to 4 operands can be given. Up to 8 operands are not supported yet (only call_vs2 and call_vn2 make use of this)."); else throw new ArgumentOutOfRangeException("operands", operands.Count(), "With OpcodeTypeKind.Var only 0 to 4 operands can be given."); } instructionForm = InstructionFormKind.Variable; operandCount = InstructionOperandCountKind.Var; } else if (opcodeType == OpcodeTypeKind.Ext) { if (operands.Count() > 4) throw new ArgumentOutOfRangeException("operands", operands.Count(), "With OpcodeTypeKind.Ext only 0 to 4 operands can be given."); instructionForm = InstructionFormKind.Extended; operandCount = InstructionOperandCountKind.Var; } else throw new ArgumentException(String.Format("Unknown OpcodeTypeKind '{0}'", opcodeType.ToString()), "opcodeType"); return new Tuple<InstructionFormKind, InstructionOperandCountKind>(instructionForm, operandCount); }
/// <summary> /// Creates a new instance of a ZInstructionBr. Check the complete table of opcodes for valid values. /// </summary> /// <param name="name">The Inform name for the used opcode. It is used for debugging purposes only, so you COULD leave this empty or null.</param> /// <param name="opcodeNumer">The opcode number.</param> /// <param name="opcodeType">The opcode type.</param> /// <param name="branch">The branch label.</param> /// <param name="operands">The operands to use.</param> public ZInstructionBr(string name, byte opcodeNumber, OpcodeTypeKind opcodeType, ZLabel branch, params ZOperand[] operands) : base(name, opcodeNumber, opcodeType, operands) { _branch = branch; _subComponents.Add(branch); }