// Path: src/main/java/uk/co/skyem/projects/emuZ80/cpu/instructionGroups/Instruction.java
// public abstract class Instruction {
// 	public InstructionDecoder instructionDecoder;
// 
// 	public Instruction(InstructionDecoder instructionDecoder) {
// 		this.instructionDecoder = instructionDecoder;
// 	}
// 
// 	/**
// 	 * Runs an opcode. Do *NOT* use setInstructionCounter from here,
// 	 * unless you don't mind your alterations being overwritten.
// 	 * Instead, use your return value. That's what it's there for!
// 	 * @param splitInstruction The instruction.
// 	 * @return The position to set the PC to. Usually, you should return splitInstruction.position, which will go forward as you read data.
// 	 */
// 	public abstract short runOpcode(InstructionDecoder.SplitInstruction splitInstruction);
// }
// 
// Path: src/main/java/uk/co/skyem/projects/emuZ80/cpu/InstructionDecoder.java
// public enum Condition {
// 	NZ(Flags.ZERO, false), Z(Flags.ZERO, true),
// 	NC(Flags.CARRY, false), C(Flags.CARRY, true),
// 	PO(Flags.PARITY_OVERFLOW, false), PE(Flags.PARITY_OVERFLOW, true),
// 	P(Flags.SIGN, false), M(Flags.SIGN, true);
// 	public final int flagVal;
// 	public final boolean expectedResult;
// 	Condition(int flag, boolean val) {
// 		flagVal = flag;
// 		expectedResult = val;
// 	}
// }


import uk.co.skyem.projects.emuZ80.cpu.*;
import uk.co.skyem.projects.emuZ80.cpu.instructionGroups.Instruction;
import uk.co.skyem.projects.emuZ80.cpu.InstructionDecoder.Condition;
package uk.co.skyem.projects.emuZ80.cpu.instructionGroups.unprefixed;


public class MiscInstruction extends Instruction {

	public MiscInstruction(InstructionDecoder instructionDecoder) {
		super(instructionDecoder);
	}

	@Override
	public short runOpcode(InstructionDecoder.SplitInstruction splitInstruction) {
		switch (splitInstruction.y) {
			case 0:
				// NOP -- Do nothing.
				break;
			case 1:
				// EX AF,AF' -- Swap AF with its shadow register.
				instructionDecoder.specialExceptionEXAF();
				break;
			case 2:
				// DJNZ d -- Decrement B by one, then relative jump if B is not zero.
				Register.Register8 b = instructionDecoder.getRegister(InstructionDecoder.Register.B, splitInstruction);
				b.decrement();
				byte relJmp = splitInstruction.getByteInc();
				if (b.getData() != 0)
					return (short) ((splitInstruction.position + relJmp) & 0xFFFF);
				break;
			case 3:
				// JR d -- Relative jump.
				// As byte is signed, there are no problems here.
				// NOTE: If z80asm is any indicator, "the jump is measured from the start of the instruction opcode" was a lie.
				//       This: http://www.phy.davidson.edu/FacHome/dmb/py310/Z80.Instruction%20set.pdf:
				//       states: "The assembler automatically adjusts for the twice incremented PC."
				//       Which is consistent with z80asm's actual output, which is based at the *end* of the instruction.
				//       Saves a headache due to prefixes - just add to splitInstruction.position after reading the relJmp offset.
				relJmp = splitInstruction.getByteInc();
				return (short) ((splitInstruction.position + relJmp) & 0xFFFF);
			case 4:
			case 5:
			case 6:
			case 7:
				// JR cc[y-4], d -- Relative jump if condition is met.
// Path: src/main/java/uk/co/skyem/projects/emuZ80/cpu/instructionGroups/Instruction.java
// public abstract class Instruction {
// 	public InstructionDecoder instructionDecoder;
// 
// 	public Instruction(InstructionDecoder instructionDecoder) {
// 		this.instructionDecoder = instructionDecoder;
// 	}
// 
// 	/**
// 	 * Runs an opcode. Do *NOT* use setInstructionCounter from here,
// 	 * unless you don't mind your alterations being overwritten.
// 	 * Instead, use your return value. That's what it's there for!
// 	 * @param splitInstruction The instruction.
// 	 * @return The position to set the PC to. Usually, you should return splitInstruction.position, which will go forward as you read data.
// 	 */
// 	public abstract short runOpcode(InstructionDecoder.SplitInstruction splitInstruction);
// }
// 
// Path: src/main/java/uk/co/skyem/projects/emuZ80/cpu/InstructionDecoder.java
// public enum Condition {
// 	NZ(Flags.ZERO, false), Z(Flags.ZERO, true),
// 	NC(Flags.CARRY, false), C(Flags.CARRY, true),
// 	PO(Flags.PARITY_OVERFLOW, false), PE(Flags.PARITY_OVERFLOW, true),
// 	P(Flags.SIGN, false), M(Flags.SIGN, true);
// 	public final int flagVal;
// 	public final boolean expectedResult;
// 	Condition(int flag, boolean val) {
// 		flagVal = flag;
// 		expectedResult = val;
// 	}
// }


// Path: src/main/java/uk/co/skyem/projects/emuZ80/cpu/instructionGroups/unprefixed/MiscInstruction.java
import uk.co.skyem.projects.emuZ80.cpu.*;
import uk.co.skyem.projects.emuZ80.cpu.instructionGroups.Instruction;
import uk.co.skyem.projects.emuZ80.cpu.InstructionDecoder.Condition;

package uk.co.skyem.projects.emuZ80.cpu.instructionGroups.unprefixed;


public class MiscInstruction extends Instruction {

	public MiscInstruction(InstructionDecoder instructionDecoder) {
		super(instructionDecoder);
	}

	@Override
	public short runOpcode(InstructionDecoder.SplitInstruction splitInstruction) {
		switch (splitInstruction.y) {
			case 0:
				// NOP -- Do nothing.
				break;
			case 1:
				// EX AF,AF' -- Swap AF with its shadow register.
				instructionDecoder.specialExceptionEXAF();
				break;
			case 2:
				// DJNZ d -- Decrement B by one, then relative jump if B is not zero.
				Register.Register8 b = instructionDecoder.getRegister(InstructionDecoder.Register.B, splitInstruction);
				b.decrement();
				byte relJmp = splitInstruction.getByteInc();
				if (b.getData() != 0)
					return (short) ((splitInstruction.position + relJmp) & 0xFFFF);
				break;
			case 3:
				// JR d -- Relative jump.
				// As byte is signed, there are no problems here.
				// NOTE: If z80asm is any indicator, "the jump is measured from the start of the instruction opcode" was a lie.
				//       This: http://www.phy.davidson.edu/FacHome/dmb/py310/Z80.Instruction%20set.pdf:
				//       states: "The assembler automatically adjusts for the twice incremented PC."
				//       Which is consistent with z80asm's actual output, which is based at the *end* of the instruction.
				//       Saves a headache due to prefixes - just add to splitInstruction.position after reading the relJmp offset.
				relJmp = splitInstruction.getByteInc();
				return (short) ((splitInstruction.position + relJmp) & 0xFFFF);
			case 4:
			case 5:
			case 6:
			case 7:
				// JR cc[y-4], d -- Relative jump if condition is met.
				Condition condition = InstructionDecoder.conditionTable[splitInstruction.y - 4];