public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; if (instruction.Condition == Condition.None || cpu.Flags.SatisfyCondition(instruction.Condition)) { cpu.Timing.InternalOperationCycle(5); ushort address = (ushort)(cpu.Registers.PC - 2); // wind back to the address of the JR instruction as PC has already moved on // the jump is relative to the address of the JR instruction but the jump *displacement* is calculated from the start of the *next* instruction. // This means the actual jump range is -126 to +129 bytes, *not* 127 bytes each way. Z80 assemblers compensate for this by // adjusting the jump value, so for example 'JR 0' would actually end up being 'JR 2' and would set PC to the start of the next // instruction - hence we must add two bytes here to resolve the correct target address address = (ushort)(address + (sbyte)data.Argument1 + 2); cpu.Registers.PC = address; cpu.Flags.X = (address & 0x08) > 0; // copy bit 3 cpu.Flags.Y = (address & 0x20) > 0; // copy bit 5 cpu.Registers.WZ = address; } return(new ExecutionResult(package, cpu.Flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; cpu.Halt(HaltReason.HaltInstruction); return(new ExecutionResult(package, null)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; sbyte offset = (sbyte)(data.Argument1); ByteRegister register = instruction.Target.AsByteRegister(); bool previousCarry = flags.Carry; byte original, shifted; if (register != ByteRegister.None) { original = r[register]; shifted = (byte)(original >> 1); shifted = shifted.SetBit(7, previousCarry); setFlags(original, shifted, original.GetBit(0)); r[register] = shifted; } else { ushort address = instruction.Prefix switch { 0xCB => r.HL, 0xDDCB => (ushort)(r.IX + offset), 0xFDCB => (ushort)(r.IY + offset), _ => (ushort)0xFFFF }; original = cpu.Memory.Timed.ReadByteAt(address); shifted = (byte)(original >> 1); shifted = shifted.SetBit(7, previousCarry); setFlags(original, shifted, original.GetBit(0)); if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(4); } cpu.Memory.Timed.WriteByteAt(address, shifted); if (instruction.CopyResultTo != ByteRegister.None) { r[instruction.CopyResultTo.Value] = shifted; } } void setFlags(byte original, byte shifted, bool overflowBit) { flags = FlagLookup.BitwiseFlags(original, BitwiseOperation.RotateRightThroughCarry, previousCarry); flags.Carry = overflowBit; flags.HalfCarry = false; flags.Subtract = false; } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; byte A = r.A; int mode = 0; if ((A & 0x0F) > 0x09 || flags.HalfCarry) { mode++; } if (A > 0x99 || flags.Carry) { mode += 2; flags.Carry = true; } if (flags.Subtract && !flags.HalfCarry) { flags.HalfCarry = false; } else { if (flags.Subtract && flags.HalfCarry) { flags.HalfCarry = (A & 0x0F) < 0x06; } else { flags.HalfCarry = (A & 0x0F) >= 0x0A; } } A = mode switch { 1 => (byte)(A + (byte)(flags.Subtract ? 0xFA : 0x06)), 2 => (byte)(A + (byte)(flags.Subtract ? 0xA0 : 0x60)), 3 => (byte)(A + (byte)(flags.Subtract ? 0x9A : 0x66)), _ => A }; flags.Sign = (A & 0x80) > 0; flags.Zero = (A == 0); flags.ParityOverflow = A.EvenParity(); flags.X = (A & 0x08) > 0; // copy bit 3 flags.Y = (A & 0x20) > 0; // copy bit 5 r.A = A; return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; if (instruction.Condition == Condition.None || flags.SatisfyCondition(instruction.Condition)) { cpu.Pop(WordRegister.PC); cpu.Registers.WZ = cpu.Registers.PC; } return(new ExecutionResult(package, flags)); }
public static byte MarshalSourceByte(this Instruction instruction, InstructionData data, Processor cpu, out ushort address, out ByteRegister source) { // this fetches a byte operand value for the instruction given, adjusting how it is fetched based on the addressing of the instruction Registers r = cpu.Registers; address = 0x0000; byte value; source = instruction.Source.AsByteRegister(); if (source != ByteRegister.None) { // operand comes from another byte register directly (eg LD A,B) value = r[source]; } else { if (instruction.Argument1 == InstructionElement.ByteValue) { // operand is supplied as an argument (eg LD A,n) value = data.Argument1; } else if (instruction.Source == InstructionElement.None) { // operand is fetched from a memory location but the source and target are the same (eg INC (HL) or INC (IX+d)) address = instruction.Target.AsWordRegister() switch { WordRegister.IX => (ushort)(r.IX + (sbyte)data.Argument1), WordRegister.IY => (ushort)(r.IY + (sbyte)data.Argument1), _ => r.HL }; value = cpu.Memory.Timed.ReadByteAt(address); } else { // operand is fetched from a memory location and assigned elsewhere (eg LD A,(HL) or LD B,(IX+d)) address = instruction.Source.AsWordRegister() switch { WordRegister.IX => (ushort)(r.IX + (sbyte)data.Argument1), WordRegister.IY => (ushort)(r.IY + (sbyte)data.Argument1), _ => r.HL }; value = cpu.Memory.Timed.ReadByteAt(address); } } return(value); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; byte t_index = instruction.Opcode.GetByteFromBits(3, 3); ushort address = (ushort)(t_index * 8); cpu.Push(WordRegister.PC); cpu.Registers.PC = (address); cpu.Registers.WZ = cpu.Registers.PC; return(new ExecutionResult(package, null)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Registers r = cpu.Registers; Flags flags = cpu.Flags; int result = 0x00 - r.A; flags = FlagLookup.ByteArithmeticFlags(0x00, r.A, false, true); flags.ParityOverflow = r.A == 0x80; flags.Carry = r.A != 0x00; r.A = (byte)result; return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; sbyte offset = (sbyte)(data.Argument1); ByteRegister register = instruction.Target.AsByteRegister(); void setFlags(byte original) { flags = FlagLookup.BitwiseFlags(original, BitwiseOperation.ShiftLeftSetBit0, flags.Carry); flags.Carry = original.GetBit(7); flags.HalfCarry = false; flags.Subtract = false; } byte original, shifted; if (register != ByteRegister.None) { original = r[register]; shifted = (byte)((original << 1) + 1); // bit 0 is always set, adding 1 does this quicker than calling SetBit setFlags(original); r[register] = shifted; } else { ushort address = instruction.Prefix switch { 0xCB => r.HL, 0xDDCB => (ushort)(r.IX + offset), 0xFDCB => (ushort)(r.IY + offset), _ => (ushort)0xFFFF }; original = cpu.Memory.Timed.ReadByteAt(address); shifted = (byte)((original << 1) + 1); setFlags(original); cpu.Memory.Timed.WriteByteAt(address, shifted); if (instruction.CopyResultTo != ByteRegister.None) { r[instruction.CopyResultTo.Value] = shifted; } } return new ExecutionResult(package, flags); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Registers r = cpu.Registers; byte offset = data.Argument1; Flags flags = cpu.Flags; if (instruction.TargetsWordRegister) { // inc 16-bit WordRegister register = instruction.Target.AsWordRegister(); ushort value = r[register]; r[register] = (ushort)(value + 1); } else { byte value = 0; if (instruction.TargetsByteInMemory) { // inc byte in memory if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } value = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); cpu.Memory.Timed.WriteByteAt(address, (byte)(value + 1)); } else { // it's an 8-bit inc ByteRegister register = instruction.Target.AsByteRegister(); value = r[register]; r[register] = (byte)(value + 1); } bool carry = flags.Carry; flags = FlagLookup.ByteArithmeticFlags(value, 1, false, false); flags.ParityOverflow = (value == 0x7F); flags.Carry = carry; // always unaffected flags.Subtract = false; } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Registers r = cpu.Registers; Flags flags = cpu.Flags; byte bitIndex = instruction.GetBitIndex(); byte value; ByteRegister register = instruction.Source.AsByteRegister(); if (register != ByteRegister.None) { value = r[register]; // BIT b, r } else { if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } value = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); byte valueXY = instruction.IsIndexed ? address.HighByte() : r.WZ.HighByte(); // this is literally the only place the WZ value is *ever* actually used flags.X = (valueXY & 0x08) > 0; // copy bit 3 flags.Y = (valueXY & 0x20) > 0; // copy bit 5 } bool set = value.GetBit(bitIndex); flags.Sign = bitIndex == 7 && set; if (register == ByteRegister.None) { flags.Y = bitIndex == 5 && set; flags.X = bitIndex == 3 && set; } flags.Zero = !set; flags.ParityOverflow = flags.Zero; flags.HalfCarry = true; flags.Subtract = false; return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; byte @in(byte portNumber, ByteRegister toRegister, bool bc) { Port port = cpu.Ports[portNumber]; port.SignalRead(); byte input = port.ReadByte(bc); if (toRegister != ByteRegister.F) { r[toRegister] = input; } return(input); } if (instruction.Prefix == 0x00) { // IN A,(n) r.WZ = (ushort)((r.A << 8) + data.Argument1 + 1); @in(data.Argument1, ByteRegister.A, false); } else { // IN r,(C) byte input = @in(r.C, instruction.Target.AsByteRegister(), true); flags.Sign = ((sbyte)input < 0); flags.Zero = (input == 0); flags.ParityOverflow = input.EvenParity(); flags.HalfCarry = false; flags.Subtract = false; flags.X = (input & 0x08) > 0; // copy bit 3 flags.Y = (input & 0x20) > 0; // copy bit 5 r.WZ = (ushort)(r.BC + 1); } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; if (instruction.Source != InstructionElement.WordValue) { // JP HL / IX / IY cpu.Registers.PC = instruction.MarshalSourceWord(data, cpu, out ushort address); } else if (instruction.Condition == Condition.None || flags.SatisfyCondition(instruction.Condition)) { cpu.Registers.PC = data.ArgumentsAsWord; cpu.Registers.WZ = data.ArgumentsAsWord; } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } byte operand = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); int result = (r.A | operand); flags = FlagLookup.LogicalFlags(r.A, operand, LogicalOperation.Or); r.A = (byte)result; return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; bool carry = flags.Carry; byte a = cpu.Registers.A; byte b = cpu.Memory.Timed.ReadByteAt(cpu.Registers.HL); var compare = ALUOperations.Subtract(a, b, false); flags = compare.Flags; cpu.Registers.BC--; flags.ParityOverflow = (cpu.Registers.BC != 0); cpu.Registers.HL--; flags.Subtract = true; flags.Carry = carry; byte valueXY = (byte)(a - b - (flags.HalfCarry ? 1 : 0)); flags.X = (valueXY & 0x08) > 0; // copy bit 3 flags.Y = (valueXY & 0x02) > 0; // copy bit 1 (note: non-standard behaviour) bool conditionTrue = (compare.Result == 0 || cpu.Registers.BC == 0); if (conditionTrue) { cpu.Timing.InternalOperationCycle(5); cpu.Registers.WZ++; } else { cpu.Registers.PC = package.InstructionAddress; cpu.Registers.WZ = (ushort)(cpu.Registers.PC + 1); } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; byte left = r.A; byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } var sub = ALUOperations.Subtract(left, right, false); r.A = sub.Result; flags = sub.Flags; return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; byte value = r.A; flags.Carry = value.GetBit(0); value = (byte)(value >> 1); value = value.SetBit(7, flags.Carry); flags.HalfCarry = false; flags.Subtract = false; flags.X = (value & 0x08) > 0; // copy bit 3 flags.Y = (value & 0x20) > 0; // copy bit 5 r.A = value; return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Registers r = cpu.Registers; byte bitIndex = instruction.GetBitIndex(); sbyte offset = (sbyte)(data.Argument1); ByteRegister register = instruction.Source.AsByteRegister(); if (register != ByteRegister.None) { byte value = r[register].SetBit(bitIndex, true); r[register] = value; } else { ushort address = instruction.Prefix switch { 0xCB => r.HL, 0xDDCB => (ushort)(r.IX + offset), 0xFDCB => (ushort)(r.IY + offset), _ => (ushort)0xFFFF }; if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } byte value = cpu.Memory.Timed.ReadByteAt(address); value = value.SetBit(bitIndex, true); cpu.Memory.Timed.WriteByteAt(address, value); if (instruction.CopyResultTo != ByteRegister.None) { r[instruction.CopyResultTo.Value] = value; } } return(new ExecutionResult(package, null)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; byte value = cpu.Memory.Timed.ReadByteAt(r.HL); cpu.Memory.Timed.WriteByteAt(r.DE, value); r.HL++; r.DE++; r.BC--; flags.HalfCarry = false; flags.ParityOverflow = (r.BC != 0); flags.Subtract = false; flags.X = (((byte)(value + cpu.Registers.A)) & 0x08) > 0; // copy bit 3 flags.Y = (((byte)(value + cpu.Registers.A)) & 0x02) > 0; // copy bit 1 (note: non-standard behaviour) return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; if (instruction.TargetsWordRegister) { // it's one of the 16-bit adds (HL,DE etc) WordRegister destination = instruction.Target.AsWordRegister(); ushort left = r[destination]; ushort right = instruction.MarshalSourceWord(data, cpu, out ushort address); cpu.Timing.InternalOperationCycle(4); cpu.Timing.InternalOperationCycle(3); var sum = ALUOperations.Add(left, right, false, false, flags); r[destination] = sum.Result; flags = sum.Flags; r.WZ = (ushort)(left + 1); } else { // it's an 8-bit add to A byte left = r.A; if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); var sum = ALUOperations.Add(left, right, false); r.A = sum.Result; flags = sum.Flags; } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Registers r = cpu.Registers; Flags flags = cpu.Flags; byte left = r.A; if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); var sub = ALUOperations.Subtract(left, right, false); flags = sub.Flags; flags.X = (right & 0x08) > 0; // copy bit 3 of operand, not result flags.Y = (right & 0x20) > 0; // copy bit 5 of operand, not result return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; Port port = cpu.Ports[r.C]; byte output = cpu.Memory.Timed.ReadByteAt(r.HL); r.WZ = r.BC; r.B--; port.SignalWrite(); port.WriteByte(output, true); r.HL++; flags.Zero = (r.B == 0); flags.Subtract = true; flags.X = (output & 0x08) > 0; // copy bit 3 flags.Y = (output & 0x20) > 0; // copy bit 5 return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; if (instruction.TargetsWordRegister) { ushort left = r.HL; cpu.Timing.InternalOperationCycle(4); cpu.Timing.InternalOperationCycle(3); ushort right = instruction.MarshalSourceWord(data, cpu, out ushort address); var subtraction = ALUOperations.Subtract(left, right, flags.Carry, true, flags); r.HL = subtraction.Result; flags = subtraction.Flags; r.WZ = (ushort)(left + 1); } else { byte left = r.A; if (instruction.IsIndexed) { cpu.Timing.InternalOperationCycle(5); } byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source); var subtraction = ALUOperations.Subtract(left, right, flags.Carry); r.A = subtraction.Result; flags = subtraction.Flags; } return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; byte xHL = cpu.Memory.Timed.ReadByteAt(cpu.Registers.HL); byte a = cpu.Registers.A; // result = (HL) = LO: high-order bits of (HL) + HI: high-order bits of A // A = LO: low-order bits of (HL) + HI: low-order bits of A bool[] lowA = a.GetLowNybble(); a = a.SetLowNybble(xHL.GetHighNybble()); xHL = xHL.SetHighNybble(xHL.GetLowNybble()); xHL = xHL.SetLowNybble(lowA); cpu.Timing.InternalOperationCycle(4); cpu.Memory.Timed.WriteByteAt(cpu.Registers.HL, xHL); cpu.Registers.A = a; // bitwise flag lookup doesn't work for this instruction flags.Sign = ((sbyte)a < 0); flags.Zero = (a == 0); flags.ParityOverflow = a.EvenParity(); flags.HalfCarry = false; flags.Subtract = false; flags.X = (a & 0x08) > 0; // copy bit 3 flags.Y = (a & 0x20) > 0; // copy bit 5 // leave carry alone cpu.Registers.WZ = (ushort)(cpu.Registers.HL + 1); return(new ExecutionResult(package, flags)); }
public ExecutionResult Execute(Processor cpu, InstructionPackage package) { Instruction instruction = package.Instruction; InstructionData data = package.Data; Flags flags = cpu.Flags; Registers r = cpu.Registers; byte arg0 = data.Argument1; byte arg1 = data.Argument2; ushort argWord = data.ArgumentsAsWord; byte readByte(ushort address) { return(cpu.Memory.Timed.ReadByteAt(address)); } ushort readWord(ushort address) { return(cpu.Memory.Timed.ReadWordAt(address)); } byte readOffset(ushort address, byte offset) { address = (ushort)(address + (sbyte)offset); byte value = cpu.Memory.Timed.ReadByteAt(address); flags.X = (address & 0x08) > 0; // copy bit 3 flags.Y = (address & 0x20) > 0; // copy bit 5 return(value); } void writeByte(ushort address, byte value) { cpu.Memory.Timed.WriteByteAt(address, value); } void writeWord(ushort address, ushort value) { cpu.Memory.Timed.WriteWordAt(address, value); } void writeOffset(ushort address, byte offset, byte value) { cpu.Memory.Timed.WriteByteAt((ushort)(address + (sbyte)offset), value); } void handleIRFlags(byte input) { flags.Zero = (input == 0x00); flags.Sign = ((sbyte)input < 0); flags.X = (input & 0x08) > 0; // copy bit 3 flags.Y = (input & 0x20) > 0; // copy bit 5 } switch (instruction.Prefix) { case 0x00: switch (instruction.Opcode) { case 0x01: // LD BC,nn r.BC = argWord; break; case 0x02: // LD (BC),A writeByte(r.BC, r.A); r.WZ = ((byte)((r.BC + 1) & 0xFF), r.A).ToWord(); break; case 0x06: // LD B,n r.B = arg0; break; case 0x0A: // LD A,(BC) r.A = readByte(r.BC); r.WZ = (ushort)(r.BC + 1); break; case 0x0E: // LD C,n r.C = arg0; break; case 0x11: // LD DE,nn r.DE = argWord; break; case 0x12: // LD (DE),A writeByte(r.DE, r.A); r.WZ = ((byte)((r.DE + 1) & 0xFF), r.A).ToWord(); break; case 0x16: // LD D,n r.D = arg0; break; case 0x1A: // LD A,(DE) r.A = readByte(r.DE); r.WZ = (ushort)(r.DE + 1); break; case 0x1E: // LD E,n r.E = arg0; break; case 0x21: // LD HL,nn r.HL = argWord; break; case 0x22: // LD (nn),HL writeWord(argWord, r.HL); break; case 0x26: // LD H,n r.H = arg0; break; case 0x2A: // LD HL,(nn) r.HL = readWord(argWord); break; case 0x2E: // LD L,n r.L = arg0; break; case 0x31: // LD SP,nn r.SP = argWord; break; case 0x32: // LD (nn),A writeByte(argWord, r.A); r.WZ = ((byte)((argWord + 1) & 0xFF), r.A).ToWord(); break; case 0x36: // LD (HL),n writeByte(r.HL, arg0); break; case 0x3A: // LD A,(nn) r.A = readByte(argWord); r.WZ = (ushort)(argWord + 1); break; case 0x3E: // LD A,n r.A = arg0; break; case 0x40: // LD B,B r.B = r.B; // yes, we have to do this, it's not just a NOP break; case 0x41: // LD B,C r.B = r.C; break; case 0x42: // LD B,D r.B = r.D; break; case 0x43: // LD B,E r.B = r.E; break; case 0x44: // LD B,H r.B = r.H; break; case 0x45: // LD B,L r.B = r.L; break; case 0x47: // LD B,A r.B = r.A; break; case 0x46: // LD B,(HL) r.B = readByte(r.HL); break; case 0x48: // LD C,B r.C = r.B; break; case 0x49: // LD C,C r.C = r.C; break; case 0x4A: // LD C,D r.C = r.D; break; case 0x4B: // LD C,E r.C = r.E; break; case 0x4C: // LD C,H r.C = r.H; break; case 0x4D: // LD C,L r.C = r.L; break; case 0x4F: // LD C,A r.C = r.A; break; case 0x4E: // LD C,(HL) r.C = readByte(r.HL); break; case 0x50: // LD D,B r.D = r.B; break; case 0x51: // LD D,C r.D = r.C; break; case 0x52: // LD D,D r.D = r.D; break; case 0x53: // LD D,E r.D = r.E; break; case 0x54: // LD D,H r.D = r.H; break; case 0x55: // LD D,L r.D = r.L; break; case 0x57: // LD D,A r.D = r.A; break; case 0x56: // LD D,(HL) r.D = readByte(r.HL); break; case 0x58: // LD E,B r.E = r.B; break; case 0x59: // LD E,C r.E = r.C; break; case 0x5A: // LD E,D r.E = r.D; break; case 0x5B: // LD E,E r.E = r.E; break; case 0x5C: // LD E,H r.E = r.H; break; case 0x5D: // LD E,L r.E = r.L; break; case 0x5F: // LD E,A r.E = r.A; break; case 0x5E: // LD E,(HL) r.E = readByte(r.HL); break; case 0x60: // LD H,B r.H = r.B; break; case 0x61: // LD H,C r.H = r.C; break; case 0x62: // LD H,D r.H = r.D; break; case 0x63: // LD H,E r.H = r.E; break; case 0x64: // LD H,H r.H = r.H; break; case 0x65: // LD H,L r.H = r.L; break; case 0x67: // LD H,A r.H = r.A; break; case 0x66: // LD H,(HL) r.H = readByte(r.HL); break; case 0x68: // LD L,B r.L = r.B; break; case 0x69: // LD L,C r.L = r.C; break; case 0x6A: // LD L,D r.L = r.D; break; case 0x6B: // LD L,E r.L = r.E; break; case 0x6C: // LD L,H r.L = r.H; break; case 0x6D: // LD L,L r.L = r.L; break; case 0x6F: // LD L,A r.L = r.A; break; case 0x6E: // LD L,(HL) r.L = readByte(r.HL); break; case 0x70: // LD (HL),B writeByte(r.HL, r.B); break; case 0x71: // LD (HL),C writeByte(r.HL, r.C); break; case 0x72: // LD (HL),D writeByte(r.HL, r.D); break; case 0x73: // LD (HL),E writeByte(r.HL, r.E); break; case 0x74: // LD (HL),H writeByte(r.HL, r.H); break; case 0x75: // LD (HL),L writeByte(r.HL, r.L); break; case 0x77: // LD (HL),A writeByte(r.HL, r.A); break; case 0x78: // LD A,B r.A = r.B; break; case 0x79: // LD A,C r.A = r.C; break; case 0x7A: // LD A,D r.A = r.D; break; case 0x7B: // LD A,E r.A = r.E; break; case 0x7C: // LD A,H r.A = r.H; break; case 0x7D: // LD A,L r.A = r.L; break; case 0x7F: // LD A,A r.A = r.A; break; case 0x7E: // LD A,(HL) r.A = readByte(r.HL); break; case 0xF9: // LD SP,HL r.SP = r.HL; break; } break; case 0xED: switch (instruction.Opcode) { case 0x43: // LD (nn),BC writeWord(argWord, r.BC); r.WZ = (ushort)(argWord + 1); break; case 0x47: // LD I,A r.I = r.A; handleIRFlags(r.A); break; case 0x4B: // LD BC,(nn) r.BC = readWord(argWord); r.WZ = (ushort)(argWord + 1); break; case 0x4F: // LD R,A r.R = r.A; handleIRFlags(r.A); break; case 0x53: // LD (nn),DE writeWord(argWord, r.DE); r.WZ = (ushort)(argWord + 1); break; case 0x57: // LD A,I r.A = r.I; handleIRFlags(r.A); flags.ParityOverflow = cpu.InterruptsPaused; break; case 0x5B: // LD DE,(nn) r.DE = readWord(argWord); r.WZ = (ushort)(argWord + 1); break; case 0x5F: // LD A,R r.A = r.R; handleIRFlags(r.A); flags.ParityOverflow = cpu.InterruptsPaused; break; case 0x73: // LD (nn),SP writeWord(argWord, r.SP); r.WZ = (ushort)(argWord + 1); break; case 0x7B: // LD SP,(nn) r.SP = readWord(argWord); r.WZ = (ushort)(argWord + 1); break; } break; case 0xDD: switch (instruction.Opcode) { case 0x21: // LD IX,nn r.IX = argWord; break; case 0x22: // LD (nn),IX writeWord(argWord, r.IX); r.WZ = (ushort)(argWord + 1); break; case 0x26: // LD IXh,n r.IXh = arg0; break; case 0x2A: // LD IX,(nn) r.IX = readWord(argWord); r.WZ = (ushort)(argWord + 1); break; case 0x2E: // LD IXl,n r.IXl = arg0; break; case 0x36: // LD (IX+o),n cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, arg1); break; case 0x44: // LD B,IXh r.B = r.IXh; break; case 0x45: // LD B,IXl r.B = r.IXl; break; case 0x46: // LD B,(IX+o) cpu.Timing.InternalOperationCycle(5); r.B = readOffset(r.IX, arg0); break; case 0x4C: // LD C,IXh r.C = r.IXh; break; case 0x4D: // LD C,IXl r.C = r.IXl; break; case 0x4E: // LD C,(IX+o) cpu.Timing.InternalOperationCycle(5); r.C = readOffset(r.IX, arg0); break; case 0x54: // LD D,IXh r.D = r.IXh; break; case 0x55: // LD D,IXl r.D = r.IXl; break; case 0x56: // LD D,(IX+o) cpu.Timing.InternalOperationCycle(5); r.D = readOffset(r.IX, arg0); break; case 0x5C: // LD E,IXh r.E = r.IXh; break; case 0x5D: // LD E,IXl r.E = r.IXl; break; case 0x5E: // LD E,(IX+o) cpu.Timing.InternalOperationCycle(5); r.E = readOffset(r.IX, arg0); break; case 0x60: // LD IXh,B r.IXh = r.B; break; case 0x61: // LD IXh,C r.IXh = r.C; break; case 0x62: // LD IXh,D r.IXh = r.D; break; case 0x63: // LD IXh,E r.IXh = r.E; break; case 0x64: // LD IXh,IXh r.IXh = r.IXh; break; case 0x65: // LD IXh,IXl r.IXh = r.IXl; break; case 0x67: // LD IXh,A r.IXh = r.A; break; case 0x66: // LD H,(IX+o) cpu.Timing.InternalOperationCycle(5); r.H = readOffset(r.IX, arg0); break; case 0x68: // LD IXl,B r.IXl = r.B; break; case 0x69: // LD IXl,C r.IXl = r.C; break; case 0x6A: // LD IXl,D r.IXl = r.D; break; case 0x6B: // LD IXl,E r.IXl = r.E; break; case 0x6C: // LD IXl,IXh r.IXl = r.IXh; break; case 0x6D: // LD IXl,IXl r.IXl = r.IXl; break; case 0x6F: // LD IXl,A r.IXl = r.A; break; case 0x6E: // LD L,(IX+o) cpu.Timing.InternalOperationCycle(5); r.L = readOffset(r.IX, arg0); break; case 0x70: // LD (IX+o),B cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.B); break; case 0x71: // LD (IX+o),C cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.C); break; case 0x72: // LD (IX+o),D cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.D); break; case 0x73: // LD (IX+o),E cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.E); break; case 0x74: // LD (IX+o),H cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.H); break; case 0x75: // LD (IX+o),L cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.L); break; case 0x77: // LD (IX+o),A cpu.Timing.InternalOperationCycle(5); writeOffset(r.IX, arg0, r.A); break; case 0x7C: // LD A,IXh r.A = r.IXh; break; case 0x7D: // LD A,IXl r.A = r.IXl; break; case 0x7E: // LD A,(IX+o) cpu.Timing.InternalOperationCycle(5); r.A = readOffset(r.IX, arg0); break; case 0xF9: // LD SP,IX r.SP = r.IX; break; } break; case 0xFD: switch (instruction.Opcode) { case 0x21: // LD IY,nn r.IY = argWord; break; case 0x22: // LD (nn),IY writeWord(argWord, r.IY); r.WZ = (ushort)(argWord + 1); break; case 0x26: // LD IYh,n r.IYh = arg0; break; case 0x2A: // LD IY,(nn) r.IY = readWord(argWord); r.WZ = (ushort)(argWord + 1); break; case 0x2E: // LD IYl,n r.IYl = arg0; break; case 0x36: // LD (IY+o),n cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, arg1); break; case 0x44: // LD B,IYh r.B = r.IYh; break; case 0x45: // LD B,IYl r.B = r.IYl; break; case 0x46: // LD B,(IY+o) cpu.Timing.InternalOperationCycle(5); r.B = readOffset(r.IY, arg0); break; case 0x4C: // LD C,IYh r.C = r.IYh; break; case 0x4D: // LD C,IYl r.C = r.IYl; break; case 0x4E: // LD C,(IY+o) cpu.Timing.InternalOperationCycle(5); r.C = readOffset(r.IY, arg0); break; case 0x54: // LD D,IYh r.D = r.IYh; break; case 0x55: // LD D,IYl r.D = r.IYl; break; case 0x56: // LD D,(IY+o) cpu.Timing.InternalOperationCycle(5); r.D = readOffset(r.IY, arg0); break; case 0x5C: // LD E,IYh r.E = r.IYh; break; case 0x5D: // LD E,IYl r.E = r.IYl; break; case 0x5E: // LD E,(IY+o) cpu.Timing.InternalOperationCycle(5); r.E = readOffset(r.IY, arg0); break; case 0x60: // LD IYh,B r.IYh = r.B; break; case 0x61: // LD IYh,C r.IYh = r.C; break; case 0x62: // LD IYh,D r.IYh = r.D; break; case 0x63: // LD IYh,E r.IYh = r.E; break; case 0x64: // LD IYh,IYh r.IYh = r.IYh; break; case 0x65: // LD IYh,IYl r.IYh = r.IYl; break; case 0x67: // LD IYh,A r.IYh = r.A; break; case 0x66: // LD H,(IY+o) cpu.Timing.InternalOperationCycle(5); r.H = readOffset(r.IY, arg0); break; case 0x68: // LD IYl,B r.IYl = r.B; break; case 0x69: // LD IYl,C r.IYl = r.C; break; case 0x6A: // LD IYl,D r.IYl = r.D; break; case 0x6B: // LD IYl,E r.IYl = r.E; break; case 0x6C: // LD IYl,IYh r.IYl = r.IYh; break; case 0x6D: // LD IYl,IYl r.IYl = r.IYl; break; case 0x6F: // LD IYl,A r.IYl = r.A; break; case 0x6E: // LD L,(IY+o) cpu.Timing.InternalOperationCycle(5); r.L = readOffset(r.IY, arg0); break; case 0x70: // LD (IY+o),B cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.B); break; case 0x71: // LD (IY+o),C cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.C); break; case 0x72: // LD (IY+o),D cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.D); break; case 0x73: // LD (IY+o),E cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.E); break; case 0x74: // LD (IY+o),H cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.H); break; case 0x75: // LD (IY+o),L cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.L); break; case 0x77: // LD (IY+o),A cpu.Timing.InternalOperationCycle(5); writeOffset(r.IY, arg0, r.A); break; case 0x7C: // LD A,IYh r.A = r.IYh; break; case 0x7D: // LD A,IYl r.A = r.IYl; break; case 0x7E: // LD A,(IY+o) cpu.Timing.InternalOperationCycle(5); r.A = readOffset(r.IY, arg0); break; case 0xF9: // LD SP,IY r.SP = r.IY; break; } break; } return(new ExecutionResult(package, flags)); }
public InstructionPackage(Instruction instruction, InstructionData data, ushort instructionAddress) { Instruction = instruction; Data = data; InstructionAddress = instructionAddress; }