public void ForZeropageIndexedMode(AddressingMode mode, RegisterName register) { memory.SetValue(0x0070, 0x8); model.GetRegister(register).SetValue(0x10); Assert.That(ArgumentUtils.ArgumentFor(model, memory, mode, 0x60), Is.EqualTo(0x8)); }
public void ReturnsTrueWhenAPageBoundaryWasCrossed(AddressingMode mode, RegisterName register) { model.GetRegister(register).SetValue(0x10); Assert.That(ArgumentUtils.CrossesPageBoundary(model, mode, 0x10F0), Is.True, "A page boundary was crossed, but not noticed."); }
public void ReturnsFalseWhenAPageBoundaryWasNotCrossed(AddressingMode mode, RegisterName register) { model.GetRegister(register).SetValue(0x10); Assert.That(ArgumentUtils.CrossesPageBoundary(model, mode, 0x10E0), Is.False, "We reported incorrectly that a page boundary was crossed."); }
public void ReturnsTheProperNumberOfCyclesWhenNotCrossingPageBoundary( AddressingMode mode, RegisterName register) { model.GetRegister(register).SetValue(0x10); Assert.That(executor.Execute(opcode, mode, 0x10E0), Is.EqualTo(InstructionTestDouble.NumberOfCycles)); }
public AddressInformation(AddressingMode destinationAddressingMode, AddressingMode sourceAddressingMode, bool intraPan, ArraySegment<byte> data) { var internalOffset = 0; if(destinationAddressingMode != AddressingMode.None) { DestinationPan = GetValue(data, 0); DestinationAddress = new Address(new ArraySegment<byte>(data.Array, data.Offset + 2, destinationAddressingMode.GetBytesLength())); internalOffset = 2 + DestinationAddress.Bytes.Count; } if(sourceAddressingMode != AddressingMode.None) { if(intraPan) { SourcePan = DestinationPan; } else { SourcePan = GetValue(data, internalOffset); internalOffset += 2; } SourceAddress = new Address(new ArraySegment<byte>(data.Array, data.Offset + internalOffset, sourceAddressingMode.GetBytesLength())); } Bytes = data; }
public Address(AddressingMode mode) { if(mode != AddressingMode.ShortAddress && mode != AddressingMode.ExtendedAddress) { throw new ArgumentException("Unsupported addressing mode"); } Bytes = new byte[mode.GetBytesLength()]; }
public void IncrementsThePCAferReadingAOneByteOperand(AddressingMode mode) { const ushort initialAddress = 0xFF10; model.GetRegister(RegisterName.PC).SetValue(initialAddress); fetcher.Fetch(); fetcher.OperandFor(mode); Assert.That(model.GetRegister(RegisterName.PC).GetValue(), Is.EqualTo(initialAddress + 2)); }
public void GetsOneByteTheOperandFor(AddressingMode mode) { const ushort address = 0xFF10; const byte expectedOperand = 0xC2; model.GetRegister(RegisterName.PC).SetValue(address); memory.SetValue(address + 1, expectedOperand); fetcher.Fetch(); Assert.That(fetcher.OperandFor(mode), Is.EqualTo(expectedOperand)); }
public ushort OperandFor(AddressingMode mode) { ushort operand = ReadPCAndIncrement(); if (mode == AddressingMode.Absolute || mode == AddressingMode.AbsoluteX || mode == AddressingMode.AbsoluteY) { byte operandHigh = ReadPCAndIncrement(); operand = (ushort)((operandHigh << 8) | operand); } return operand; }
public static DeviceSampler Create(Boolean normalizedCoords, AddressingMode addressingMode, FilterMode filterMode, Context context) { CLError error = new CLError(); CLSampler sampler = OpenCLDriver.clCreateSampler(context.CLContext, normalizedCoords ? CLBool.True : CLBool.False, (CLAddressingMode)addressingMode, (CLFilterMode)filterMode, ref error); OpenCLError.Validate(error); return new DeviceSampler() { openCLSampler = sampler }; }
public void GetsTwoByteTheOperandFor(AddressingMode mode) { const ushort address = 0xFF10; const byte operandLow = 0xC2; const byte operandHigh = 0x59; ushort expectedOperand = (operandHigh << 8) | operandLow; model.GetRegister(RegisterName.PC).SetValue(address); memory.SetValue(address + 1, operandLow); memory.SetValue(address + 2, operandHigh); fetcher.Fetch(); Assert.That(fetcher.OperandFor(mode), Is.EqualTo(expectedOperand)); }
public int Execute(Opcode opcode, AddressingMode mode, ushort operand) { byte argument = 0; if (mode != AddressingMode.Implied) argument = ArgumentUtils.ArgumentFor(model, memory, mode, operand); var instruction = registry.Get(opcode); instruction.Execute(model, memory, argument); var numberOfCycles = instruction.CyclesFor(mode); if (ArgumentUtils.CrossesPageBoundary(model, mode, operand)) numberOfCycles++; return numberOfCycles; }
public static bool CrossesPageBoundary(ProgrammingModel model, AddressingMode mode, ushort operand) { if (mode == AddressingMode.AbsoluteX) { var address = OffsetAddressFor(model, RegisterName.X, operand); return (operand & 0xFF00) != (address & 0xFF00); } else if (mode == AddressingMode.AbsoluteY) { var address = OffsetAddressFor(model, RegisterName.Y, operand); return (operand & 0xFF00) != (address & 0xFF00); } return false; }
public void FindsTheProperOpCodeAndAddressingModeForTheInstruction( byte instruction, Opcode expectedOpcode, AddressingMode expectedAddressingMode) { var registry = new Registry { { instruction, expectedOpcode, null, expectedAddressingMode } }; var decoder = new Decoder(registry); OpcodeAddressModePair pair; var hasInstruction = decoder.TryDecode(instruction, out pair); Assert.That(hasInstruction, Is.True, @"Try Decode returned false for a valid instruction, which is not expected."); Assert.That(pair.Opcode, Is.EqualTo(expectedOpcode)); Assert.That(pair.Mode, Is.EqualTo(expectedAddressingMode)); }
private string AddressOperandToString(AddressingMode mode, ushort address, byte value = 0) { switch (mode) { case AddressingMode.Implicit: return(""); case AddressingMode.Immediate: return($"#{value:X2}"); case AddressingMode.Relative: var saddr = (sbyte)address; var ssign = saddr < 0 ? "-" : "+"; var sstr = saddr < 0 ? -saddr : saddr; return($"*{ssign}{sstr:X}"); case AddressingMode.ZeroPage: return($"{address:X2}"); case AddressingMode.ZeroPageX: return($"{address:X2},X"); case AddressingMode.ZeroPageY: return($"{address:X2},Y"); case AddressingMode.Absolute: return($"{address:X4}"); case AddressingMode.AbsoluteX: return($"{address:X4},X"); case AddressingMode.AbsoluteY: return($"{address:X4},Y"); case AddressingMode.Indirect: return($"({address:X4})"); case AddressingMode.IndirectX: return($"({address:X2},X)"); case AddressingMode.IndirectY: return($"({address:X2}),Y"); default: return($"?{address:X4}"); } }
private int GetAddress(AddressingMode mode, byte byte1, byte byte2) { switch (mode) { case AddressingMode.IndexedIndirectX: { int addr = byte1 + registers.X; return(memory[addr] + 256 * memory[addr + 1]); } case AddressingMode.IndirectIndexedY: { byte b1 = memory[byte1]; byte b2 = memory[byte1 + 1]; return(GetAddress(AddressingMode.AbsoluteY, b1, b2)); } case AddressingMode.Indirect: return(GetAddress(AddressingMode.Absolute, memory[byte1 + byte2 * 256], memory[byte1 + byte2 * 256 + 1])); case AddressingMode.Absolute: return(byte1 + byte2 * 256); case AddressingMode.AbsoluteX: return(byte1 + byte2 * 256 + registers.X); case AddressingMode.AbsoluteY: return(byte1 + byte2 * 256 + registers.Y); case AddressingMode.ZeroPage: return(byte1); case AddressingMode.ZeroPageX: return(byte1 + registers.X); case AddressingMode.ZeroPageY: return(byte1 + registers.Y); case AddressingMode.Implied: case AddressingMode.Relative: case AddressingMode.Accumulator: case AddressingMode.Immidiate: default: throw new InvalidOperationException("Invalid addressiong mode."); } }
public static int GetBytesLength(this AddressingMode mode) { switch (mode) { case AddressingMode.None: return(0); case AddressingMode.ShortAddress: return(2); case AddressingMode.ExtendedAddress: return(8); default: throw new ArgumentException(); } }
/// <summary> /// Logical Shift Right /// </summary> private byte LSR(AddressingMode mode, byte opcodeSize, byte cycles, bool oopsCycle) { var value = ReadValue(mode, out _); SetStatusFlag(Status.Carry, value.IsBitSet(0)); value >>= 1; WriteValue(mode, value); CheckZero(value); CheckNegative(value); pc += opcodeSize; return(cycles); }
/// <summary> /// Operand dispatch /// </summary> private static Operand DispatchOperand(ushort word, AddressingMode addressingMode, OperandNotation notation, ushort relativeValue) { Operand _ret = new Operand() { AddressingMode = addressingMode, Notation = notation }; switch (addressingMode) { case AddressingMode.Immediate: // immediate number word += relativeValue; _ret.Value = word; _ret.Symbol = string.Format("${0}", Convert.ToString(word, 16).ToUpper().PadLeft(4, '0')); break; case AddressingMode.MemoryReference: // memory location word += relativeValue; _ret.Value = word; _ret.Symbol = string.Format("(${0})", Convert.ToString(word, 16).ToUpper().PadLeft(4, '0')); break; case AddressingMode.ImmediateQuick: // immediate nibble operand bits 111100 _ret.Value = (ushort)((word >> 2) & 0x0f); _ret.Symbol = string.Format("{0}", _ret.Value); break; case AddressingMode.RegisterDirect: // register index _ret.Value = (ushort)((word >> (notation == OperandNotation.Destination ? 6 : 2)) & 0x07); _ret.Symbol = string.Format("A{0}", _ret.Value); break; case AddressingMode.RegisterReference: // register index _ret.Value = (ushort)((word >> (notation == OperandNotation.Destination ? 6 : 2)) & 0x07); _ret.Symbol = string.Format("(A{0})", _ret.Value); break; } return(_ret); }
public byte ReadByte(AddressingMode mode, byte address, byte registerVal = 0) { switch (mode) { case AddressingMode.Immediate: return(address); case AddressingMode.ZeroPage: return((byte)(memory[address])); case AddressingMode.ZeroPageIndexed: return(memory[(address + registerVal) % 256]); case AddressingMode.AbsoluteIndexed: return(memory[address + registerVal]); case AddressingMode.IndexedIndirectX: return(memory[(memory[(address + this.X) % 256] + memory[((address + this.X + 1) % 256)] * 256)]); case AddressingMode.IndirectIndexedY: return(memory[(memory[address] + memory[((address + 1) % 256)] * 256 + this.Y)]); } throw new NotImplementedException(); }
public byte[] Read(IntPtr address, int size, AddressingMode addressingMode = AddressingMode.Absolute) { byte[] data = new byte[size]; address = ResolveAddress(address, addressingMode); bool success = ReadProcessMemory(processHandle, address, data, (uint)data.Length, out uint bytesRead); // Make sure we read successfully. if (!success || bytesRead != (uint)data.Length) { throw new ProcessMemoryReadException( address, success, bytesRead, data.Length ); } return(data); }
/// <summary> /// Read a class/struct from process memory. /// </summary> /// <typeparam name="T">The type to read.</typeparam> /// <param name="address">Process memory address of struct.</param> /// <param name="addressingMode">Absolute or relative memory addressing.</param> /// <returns>The deserialized value or null.</returns> public T Read <T>(IntPtr address, AddressingMode addressingMode = AddressingMode.Absolute) { // Read struct memory. byte[] buffer = Read(address, Marshal.SizeOf <T>(), addressingMode); // Convert to structure. T data = default(T); GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); try { data = Marshal.PtrToStructure <T>(handle.AddrOfPinnedObject()); } finally { handle.Free(); } return(data); }
/// <summary> /// Load Y Register /// </summary> private byte LDY(AddressingMode mode, byte opcodeSize, byte cycles, bool oopsCycle) { var value = ReadValue(mode, out bool crossedPage, oopsCycle); y = value; CheckZero(y); CheckNegative(y); pc += opcodeSize; if (crossedPage) { cycles++; } return(cycles); }
private void BitTest(byte position, AddressingMode source) { bool bitIsSet = (ALURightBuffer & (1 << position)) != 0; // SF flag Set if n = 7 and tested bit is set. SF = bitIsSet && position == 7; // ZF flag Set if the tested bit is reset. ZF = !bitIsSet; // PF flag Set just like ZF flag. PF = ZF; // HF flag Always set. HF = true; // NF flag Always reset. NF = false; // CF flag Unchanged. // Bits 3 and 5 are computed below F &= B11010111; // Contrary to what is said in Z80-Undocumented, // bits 3 and 5 are always copied from the test value // for BIT n,r if (source == AddressingMode.Register) { F |= (byte)(ALURightBuffer & B00101000); } // With the BIT n,(IX+d) instructions, YF and XF are not copied from the result but from something // completely different, namely bit 5 and 3 of the high byte of IX+d (so IX plus the displacement). else if (source == AddressingMode.Indexed) { F |= (byte)((InternalAddressBus >> 8) & B00101000); } // With the BIT n,(HL) instruction. YF and XF are copied from internal register MEMPTR. else if (source == AddressingMode.RegisterIndirect) { F |= (byte)(W & B00101000); } if (TraceMicroInstructions) { TraceMicroInstruction(new MicroInstruction(Z80MicroInstructionTypes.BitOperationTest, position, source)); } }
public static IAddressing Get(AddressingMode addrMode) { return(addrMode switch { AddressingMode.ImplicitAddressingMode => ImplicitAddressingMode, AddressingMode.AccumulatorAddressingMode => AccumulatorAddressingMode, AddressingMode.ImmediateAddressingMode => ImmediateAddressingMode, AddressingMode.AbsoluteAddressingMode => AbsoluteAddressingMode, AddressingMode.AbsoluteXAddressingMode => AbsoluteXAddressingMode, AddressingMode.AbsoluteYAddressingMode => AbsoluteYAddressingMode, AddressingMode.ZeroPageAddressingMode => ZeroPageAddressingMode, AddressingMode.ZeroPageXAddressingMode => ZeroPageXAddressingMode, AddressingMode.ZeroPageYAddressingMode => ZeroPageYAddressingMode, AddressingMode.RelativeAddressingMode => RelativeAddressingMode, AddressingMode.IndirectAddressingMode => IndirectAddressingMode, AddressingMode.IndirectXAddressingMode => IndirectXAddressingMode, AddressingMode.IndirectYAddressingMode => IndirectYAddressingMode, _ => throw new UnknownAddressingModeException(addrMode) });
public void SetByte(AddressingMode mode, ushort addr, byte value, byte registerVal = 0) { switch (mode) { case AddressingMode.Absolute: memory[addr] = value; break; case AddressingMode.ZeroPage: memory[addr] = value; break; case AddressingMode.ZeroPageIndexed: memory[(addr + registerVal) % 256] = value; break; case AddressingMode.AbsoluteIndexed: memory[addr + registerVal] = value; break; case AddressingMode.IndexedIndirectX: memory[(memory[(addr + this.X) % 256] + memory[((addr + this.X + 1) % 256)] * 256)] = value; break; case AddressingMode.IndirectIndexedY: memory[(memory[addr] + memory[((addr + 1) % 256)] * 256 + this.Y)] = value; break; default: throw new NotImplementedException(); } }
public long Read(long index, AddressingMode am) { var valueAtIndex = Get(index); switch (am) { case AddressingMode.Position: return(Get(valueAtIndex)); case AddressingMode.Relative: return(Get(relativeBase + valueAtIndex)); case AddressingMode.Immediate: return(valueAtIndex); default: throw new NotImplementedException(); } }
//Overriding the SBC operaiton to remove decimal mode protected override void SubtractWithBorrowOperation(AddressingMode addressingMode) { var memoryValue = ReadMemoryValue(GetAddressByAddressingMode(addressingMode)); var newValue = Accumulator - memoryValue - (CarryFlag ? 0 : 1); CarryFlag = newValue >= 0; OverflowFlag = (((Accumulator ^ newValue) & 0x80) != 0) && (((Accumulator ^ memoryValue) & 0x80) != 0); if (newValue < 0) { newValue += 256; } SetNegativeFlag(newValue); SetZeroFlag(newValue); Accumulator = newValue; }
/// <summary> /// Reads a string from memory and chops it off at the null terminator. /// If there is no null terminator it's just returned with the size specified, this /// might chop up a word if the string is too long. /// </summary> /// <param name="address">What address to read from.</param> /// <param name="size">Size of buffer to read string into.</param> /// <param name="encoding">String encoding type.</param> /// <param name="addressing">Module addressing mode.</param> /// <returns></returns> public string ReadNullTerminatedString( IntPtr address, int size, Encoding encoding, AddressingMode addressing = AddressingMode.Absolute ) { // Get entire string buffer as string. string value = ReadStringRaw(address, size, encoding, addressing); // Find the null terminator and chop the string there. int nullTerminatorIndex = value.IndexOf('\0'); if (nullTerminatorIndex >= 0) { value = value.Remove(nullTerminatorIndex); } return(value); }
public static byte ArgumentFor(ProgrammingModel model, Memory memory, AddressingMode mode, ushort operand) { ushort address = 0; if (mode == AddressingMode.Immediate) return (byte)operand; else if (mode == AddressingMode.Absolute || mode == AddressingMode.Zeropage) address = operand; else if (mode == AddressingMode.AbsoluteX || mode == AddressingMode.ZeropageX) address = OffsetAddressFor(model, RegisterName.X, operand); else if (mode == AddressingMode.AbsoluteY || mode == AddressingMode.ZeropageY) address = OffsetAddressFor(model, RegisterName.Y, operand); else if (mode == AddressingMode.IndexedIndirectX) address = IndexedIndirectAddressFor(model, memory, RegisterName.X, operand); else if (mode == AddressingMode.IndexedIndirectY) address = IndexedIndirectAddressFor(model, memory, RegisterName.Y, operand); return memory.GetValue(address); }
public OpCodeDefinition( byte opCode, OpCode nemonic, AddressingMode addressingMode, byte instructionBytes, byte executionCycles, bool addExecutionCycleOnPageBoundaryCross, string affectedFlags, bool illegalOpCode = false) { OpCode = opCode; Nemonic = nemonic; AddressingMode = addressingMode; InstructionBytes = instructionBytes; ExecutionCycles = executionCycles; AddExecutionCycleOnPageBoundaryCross = addExecutionCycleOnPageBoundaryCross; AffectedFlags = affectedFlags; IllegalOpCode = illegalOpCode; }
private ushort GetInstructionArgumentAddress(AddressingMode mode) { var argumentAddress = (ushort)(programCounter + 1); switch (mode) { case AddressingMode.Absolute: return(ReadShort(argumentAddress)); case AddressingMode.AbsoluteX: return((ushort)(ReadShort(argumentAddress) + x)); case AddressingMode.AbsoluteY: return((ushort)(ReadShort(argumentAddress) + y)); case AddressingMode.ZeroPage: return(ReadByte(argumentAddress)); case AddressingMode.ZeroPageX: return((byte)(ReadByte(argumentAddress) + x)); case AddressingMode.ZeroPageY: return((byte)(ReadByte(argumentAddress) + y)); case AddressingMode.Immediate: return(argumentAddress); case AddressingMode.Relative: { var offset = ReadByte(argumentAddress); return(offset < 0x80 ? (ushort)(programCounter + 2 + offset) : (ushort)(programCounter + 2 + offset - 0x100)); } case AddressingMode.Implied: return(0); case AddressingMode.Indirect: return(ReadShortBug(ReadShort(argumentAddress))); case AddressingMode.IndexedIndirectX: return(ReadShortBug((byte)(ReadByte(argumentAddress) + x))); case AddressingMode.IndirectIndexedY: return((ushort)(ReadShortBug(ReadByte(argumentAddress)) + y)); case AddressingMode.Accumulator: return(0); default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Retrieves the hexadecimal dump for the instruction operand based on its addressing mode. /// </summary> /// <param name="instructionOperand">The raw instruction operand.</param> /// <param name="addrMode">The instruction's addressing mode.</param> /// <returns>The hexadecimal dump of the given instruction operand.</returns> private static string[] GetOperandHexDump(string instructionOperand, AddressingMode addrMode) { var hexValues = new List <string>(); switch (addrMode) { case AddressingMode.Absolute: case AddressingMode.AbsoluteX: case AddressingMode.AbsoluteY: case AddressingMode.Indirect: { Match m = _16BitRegexPattern.Match(instructionOperand); short val = Convert.ToInt16(m.Value, 16); byte lowByte = (byte)val; byte highByte = (byte)(val >> 8); //byte lowByte = (byte)(val & 0xFF); //byte highByte = (byte)(val >> 8 & 0xFF); // 6502 CPU is little endian (low byte first and then high byte) hexValues.Add(GetHex(lowByte)); hexValues.Add(GetHex(highByte)); } break; case AddressingMode.Immediate: case AddressingMode.IndirectX: case AddressingMode.IndirectY: case AddressingMode.Relative: case AddressingMode.ZeroPage: case AddressingMode.ZeroPageX: case AddressingMode.ZeroPageY: { Match m = _8BitRegexPattern.Match(instructionOperand); byte b = Convert.ToByte(m.Value, 16); hexValues.Add(GetHex(b)); } break; } return(hexValues.ToArray()); }
public IntPtr ResolveAddressPath(IntPtr baseAddress, int[] pathOffsets, AddressingMode addressing = AddressingMode.Absolute) { if (pathOffsets == null) { return(baseAddress); } IntPtr address = baseAddress; foreach (int offset in pathOffsets) { // Read at the current address and then offset. address = IntPtr.Add(ReadAddress32(address, addressing), offset); // Assume all subsequent addressing to be absolute. addressing = AddressingMode.Absolute; } return(address); }
/// <summary> /// Rotate Left /// </summary> private byte ROL(AddressingMode mode, byte opcodeSize, byte cycles, bool oopsCycle) { var value = ReadValue(mode, out _); var oldCarry = GetStatusFlag(Status.Carry); SetStatusFlag(Status.Carry, value.IsBitSet(NegativeBit)); value <<= 1; value |= (byte)oldCarry; WriteValue(mode, value); CheckZero(a); CheckNegative(value); pc += opcodeSize; return(cycles); }
private EvaluatedOp EvalOp(GameEngine engine, Expression field, AddressingMode mode) { if (mode == AddressingMode.Immediate) { return(new EvaluatedOp(field.CalculateByMod())); } int address = field.Calculate() + engine.CurrentIp; if (mode == AddressingMode.Direct) { return(new EvaluatedOp(address, engine.Memory[address].Statement)); } if (mode == AddressingMode.PredecrementIndirect) { DecrementB(engine, address); } int inderectAddress = address + engine.Memory[address].Statement.FieldB.Calculate(); return(new EvaluatedOp(inderectAddress, engine.Memory[inderectAddress].Statement)); }
/// <summary> /// Decrement Memory /// </summary> private byte DEC(AddressingMode mode, byte opcodeSize, byte cycles, bool oopsCycle) { var value = ReadValue(mode, out bool crossedPage, oopsCycle); value--; WriteValue(mode, value); CheckZero(value); CheckNegative(value); pc += opcodeSize; if (crossedPage) { cycles++; } return(cycles); }
private static object ReadOperand(BinaryReader br, AddressingMode am) { switch (am) { case AddressingMode.DIRECT_REGISTER: return((Register)br.ReadByte()); case AddressingMode.CONDITION_CODE: return((byte)br.ReadByte()); case AddressingMode.INDIRECT_REG32: case AddressingMode.INDIRECT_REG16: case AddressingMode.INDIRECT_REG8: return(new IndirectOffset((Register)br.ReadByte(), br.ReadInt16())); case AddressingMode.IMMEDIATE_32: return(br.ReadUInt32()); } return(null); }
internal Opcode(byte code, OpcodeEnum @enum, AddressingMode mode, byte cycles) { Code = code; Enum = @enum; Mode = mode; Cycles = cycles; if (Mode == AddressingMode.Implied) { Length = 0; } else if (Mode == AddressingMode.Absolute || Mode == AddressingMode.AbsoluteX || Mode == AddressingMode.AbsoluteY || Mode == AddressingMode.Indirect) { Length = 2; } else { Length = 1; } }
/// <summary> /// Compare /// </summary> private byte CMP(AddressingMode mode, byte opcodeSize, byte cycles, bool oopsCycle) { var value = ReadValue(mode, out bool crossedPage, oopsCycle); var result = a - value; CheckZero((byte)result); SetStatusFlag(Status.Carry, result >= 0); CheckNegative((byte)result); pc += opcodeSize; if (crossedPage) { cycles++; } return(cycles); }
public void Write(long index, long value, AddressingMode am) { var valueAtIndex = Get(index); switch (am) { case AddressingMode.Position: data[valueAtIndex] = value; return; case AddressingMode.Relative: data[relativeBase + valueAtIndex] = value; return; case AddressingMode.Immediate: throw new NotImplementedException(); default: throw new NotImplementedException(); } }
public bool SetValue(AddressingMode addrMode, int dest, int value) { switch (addrMode) { case AddressingMode.reg: registers[dest] = value; break; case AddressingMode.memory: memory[dest] = value; break; case AddressingMode.immediate: return(false); case AddressingMode.memAtReg: memory[registers[dest]] = value; break; } return(true); }
private static string GenerateInstructionLineText(InstructionCode instructionCode, byte operandByte1, byte operandByte2) { InstructionType instructionType = instructionCode.InstructionType; string instructionText = "\t" + instructionType.OpCodeName; if (instructionCode.IsDuplicate) { string instrCodeBytes = ""; if (instructionCode.Prefix != null) { foreach (byte b in instructionCode.Prefix) { instrCodeBytes += b.ToString("X2") + "H "; } } instrCodeBytes += instructionCode.OpCode.ToString("X2"); instructionText += "[" + instrCodeBytes + "H]"; } if (instructionType.Param1Type.HasValue) { AddressingMode paramType = instructionType.Param1Type.Value; string enumString = instructionCode.Param1.ToString(); instructionText += " " + GetParamTextFromEnumStringAndOperand(instructionType, paramType, enumString, false, operandByte1, operandByte2); } if (instructionType.Param2Type.HasValue) { AddressingMode paramType = instructionType.Param2Type.Value; string enumString = instructionCode.Param2.ToString(); instructionText += "," + GetParamTextFromEnumStringAndOperand(instructionType, paramType, enumString, false, operandByte1, operandByte2); } if (instructionType.Param3Type.HasValue) { AddressingMode paramType = instructionType.Param3Type.Value; string enumString = instructionCode.Param3.ToString(); instructionText += "," + GetParamTextFromEnumStringAndOperand(instructionType, paramType, enumString, false, operandByte1, operandByte2); } return(instructionText); }
void Write(qbyte address, qbyte _value, AddressingMode mode) { qbyte value = _value; while (value < 0) { value += 0x10000; } while (value > 0xffff) { value -= 0x10000; } switch (mode) { case AddressingMode.Immediate: { throw new Exception("cannot write to immediate value " + address + " (value: " + value + ")"); } case AddressingMode.Absolute: { mmu.Write(address, value); } break; case AddressingMode.Indirect: { mmu.Write(Read(address, AddressingMode.Register), value); } break; case AddressingMode.Register: { registers.Set(address, value); } break; } }
/// <summary> /// Build <see cref="EntryCreateOrMoveOperationInfo" />. /// </summary> /// <param name="assetPath"></param> /// <param name="defaultAddressingMode"></param> /// <param name="defaultPackingMode"></param> /// <param name="defaultGroupTemplateGuid"></param> /// <param name="rules"></param> /// <returns></returns> public EntryCreateOrMoveOperationInfo BuildEntryCreateOrMoveInfo(string assetPath, AddressingMode defaultAddressingMode, PackingMode defaultPackingMode, string defaultGroupTemplateGuid, EntryRuleSet rules) { Assert.IsFalse(string.IsNullOrEmpty(assetPath)); Assert.IsFalse(string.IsNullOrEmpty(_assetDatabaseAdapter.GUIDToAssetPath(defaultGroupTemplateGuid))); // Do not process the folder. if (Directory.Exists(assetPath)) { return(null); } var addressablePath = _addressablePathGenerateService.GenerateFromAssetPath(assetPath); if (string.IsNullOrEmpty(addressablePath)) { return(null); } // Determine all rules. if (rules != null) { var info = BuildEntryCreateOrMoveInfoByRules(assetPath, rules, defaultGroupTemplateGuid); if (info != null) { return(info); } } // Apply the default settings if none of the rules are matched. var address = _addressGenerateDomainService.GenerateFromAddressablePath(addressablePath, defaultAddressingMode); var groupName = _groupNameGenerateService.GenerateFromAssetPath(assetPath, defaultPackingMode); var groupTemplateGuid = defaultGroupTemplateGuid; return(new EntryCreateOrMoveOperationInfo(assetPath, address, groupName, groupTemplateGuid, null)); }
private static string GetClassFromAddressingMode(AddressingMode addressingMode) { switch(addressingMode) { case AddressingMode.Bit: case AddressingMode.FlagCondition: case AddressingMode.InterruptMode: return "p_constant"; case AddressingMode.Extended: case AddressingMode.RegisterIndirect: case AddressingMode.Indexed: case AddressingMode.ModifiedPageZero: case AddressingMode.Relative: return "p_memaddr"; case AddressingMode.IOPortImmediate: case AddressingMode.IOPortRegister: return "p_portaddr"; case AddressingMode.Register: case AddressingMode.Register16: case AddressingMode.Flags: return "p_register"; case AddressingMode.Immediate: case AddressingMode.Immediate16: default: return "p_value"; } }
/// <summary> /// The SBC operation. Performs a subtract with carry operation on the accumulator and a value in memory. /// </summary> /// <param name="addressingMode">The addressing mode to use</param> private void SubtractWithBorrowOperation(AddressingMode addressingMode) { var memoryValue = Memory.ReadValue(GetAddressByAddressingMode(addressingMode)); var newValue = DecimalFlag ? int.Parse(Accumulator.ToString("x")) - int.Parse(memoryValue.ToString("x")) - (CarryFlag ? 0 : 1) : Accumulator - memoryValue - (CarryFlag ? 0 : 1); CarryFlag = newValue >= 0; if (DecimalFlag) { if (newValue < 0) newValue += 100; newValue = (int)Convert.ToInt64(string.Concat("0x", newValue), 16); } else { OverflowFlag = (((Accumulator ^ newValue) & 0x80) != 0) && (((Accumulator ^ memoryValue) & 0x80) != 0); if (newValue < 0) newValue += 256; } SetNegativeFlag(newValue); SetZeroFlag(newValue); Accumulator = newValue; }
/// <summary> /// Uses the AddressingMode to return the correct address based on the mode. /// Note: This method will not increment the program counter for any mode. /// Note: This method will return an error if called for either the immediate or accumulator modes. /// </summary> /// <param name="addressingMode">The addressing Mode to use</param> /// <returns>The memory Location</returns> private int GetAddressByAddressingMode(AddressingMode addressingMode) { int address; switch (addressingMode) { case (AddressingMode.Absolute): { //Get the first half of the address address = Memory.ReadValue(ProgramCounter); //Get the second half of the address. We multiple the value by 256 so we retrieve the right address. //IF the first Value is FF and the second value is FF the address would be FFFF. address += 256 * Memory.ReadValue(ProgramCounter + 1); return address; } case AddressingMode.AbsoluteX: { //Get the first half of the address address = Memory.ReadValue(ProgramCounter); //Get the second half of the address. We multiple the value by 256 so we retrieve the right address. //IF the first Value is FF and the second value is FF the address would be FFFF. //Then add the X Register value to that. //We don't increment the program counter here, because it is incremented as part of the operation. address += (256 * Memory.ReadValue(ProgramCounter + 1) + XRegister); //This address wraps if its greater than 0xFFFF if (address > 0xFFFF) { address = address - 0x10000; //We crossed a page boundry, so decrease the number of cycles by 1. //However, if this is an ASL operation, we do not decrease if by 1. if (CurrentOpCode == 0x1E) return Memory.ReadValue(address); NumberofCyclesLeft--; } return address; } case AddressingMode.AbsoluteY: { //Get the first half of the address address = Memory.ReadValue(ProgramCounter); //Get the second half of the address. We multiple the value by 256 so we retrieve the right address. //IF the first Value is FF and the second value is FF the address would be FFFF. //Then add the Y Register value to that. //We don't increment the program counter here, because it is incremented as part of the operation. address += (256 * Memory.ReadValue(ProgramCounter + 1) + YRegister); //This address wraps if its greater than 0xFFFF if (address > 0xFFFF) { address = address - 0x10000; //We crossed a page boundry, so decrease the number of cycles by 1. NumberofCyclesLeft--; } return address; } case AddressingMode.Immediate: { return ProgramCounter; } case AddressingMode.IndexedIndirect: { //Get the location of the address to retrieve address = Memory.ReadValue(ProgramCounter) + XRegister; //Its a zero page address, so it wraps around if greater than 0xff if (address > 0xff) address = address - 0x100; //Now get the final Address. The is not a zero page address either. var finalAddress = Memory.ReadValue(address) + (256 * Memory.ReadValue(address + 1)); return finalAddress; } case AddressingMode.IndirectIndexed: { address = Memory.ReadValue(ProgramCounter); var finalAddress = Memory.ReadValue(address) + (256 * Memory.ReadValue(address + 1)) + YRegister; //This address wraps if its greater than 0xFFFF if (finalAddress > 0xFFFF) { finalAddress = finalAddress - 0x10000; //We crossed a page boundry, so decrease the number of cycles by 1. NumberofCyclesLeft--; } return finalAddress; } case (AddressingMode.ZeroPage): { address = Memory.ReadValue(ProgramCounter); return address; } case (AddressingMode.ZeroPageX): { address = Memory.ReadValue(ProgramCounter); return address + XRegister; } case (AddressingMode.ZeroPageY): { address = Memory.ReadValue(ProgramCounter); return address + XRegister; } default: throw new InvalidEnumArgumentException(string.Format("The Addressing Mode {0} has not been implemented", addressingMode)); } }
/// <summary> /// The ADC - Add Memory to Accumulator with Carry Operation /// </summary> /// <param name="addressingMode">The addressing mode used to perform this operation.</param> private void AddWithCarryOperation(AddressingMode addressingMode) { //Accumulator, Carry = Accumulator + ValueInMemoryLocation + Carry var memoryValue = Memory.ReadValue(GetAddressByAddressingMode(addressingMode)); var newValue = memoryValue + Accumulator + (CarryFlag ? 1 : 0); SetOverflow(Accumulator, memoryValue, newValue); if (IsInDecimalMode) { if (newValue > 99) { CarryFlag = true; newValue -= 100; } else { CarryFlag = false; } } else { if (newValue > 255) { CarryFlag = true; newValue -= 256; } else { CarryFlag = false; } } SetIsResultZero(newValue); SetIsSignNegative(newValue); Accumulator = newValue; }
/// <summary> /// Changes a value in memory by 1 /// </summary> /// <param name="addressingMode">The addressing mode to use</param> /// <param name="decrement">If the operation is decrementing or incrementing the vaulue by 1 </param> private void ChangeMemoryByOne(AddressingMode addressingMode, bool decrement) { var memoryLocation = GetAddressByAddressingMode(addressingMode); var memory = Memory.ReadValue(memoryLocation); if (decrement) memory -= 1; else memory += 1; SetZeroFlag(memory); SetNegativeFlag(memory); Memory.WriteValue(memoryLocation,memory); }
/// <summary> /// The compare operation. This operation compares a value in memory with a value passed into it. /// </summary> /// <param name="addressingMode">The addressing mode to use</param> /// <param name="comparisonValue">The value to compare against memory</param> private void CompareOperation(AddressingMode addressingMode, int comparisonValue) { var memoryValue = Memory.ReadValue(GetAddressByAddressingMode(addressingMode)); var comparedValue = comparisonValue - memoryValue; if (comparedValue < 0) comparedValue += 0x10000; SetZeroFlag(comparedValue); CarryFlag = memoryValue <= comparisonValue; SetNegativeFlag(comparedValue); }
/// <summary> /// The bit operation, does an & comparison between a value in memory and the accumulator /// </summary> /// <param name="addressingMode"></param> private void BitOperation(AddressingMode addressingMode) { var memoryValue = Memory.ReadValue(GetAddressByAddressingMode(addressingMode)); var valueToCompare = memoryValue & Accumulator; OverflowFlag = (memoryValue & 0x40) != 0; SetNegativeFlag(memoryValue); SetZeroFlag(valueToCompare); }
public void ReturnsTheProperNumberOfCycles(AddressingMode mode, int expected) { Assert.That(new And().CyclesFor(mode), Is.EqualTo(expected)); }
/// <summary> /// The LSR Operation. Performs a Left shift operation on a value in memory /// </summary> /// <param name="addressingMode">The addressing mode to use</param> private void LsrOperation(AddressingMode addressingMode) { int value; var memoryAddress = 0; if (addressingMode == AddressingMode.Accumulator) value = Accumulator; else { memoryAddress = GetAddressByAddressingMode(addressingMode); value = Memory.ReadValue(memoryAddress); } NegativeFlag = false; //If the Zero bit is set, we have a carry CarryFlag = ( value & 0x01 ) != 0; value = (value >> 1); SetZeroFlag(value); if (addressingMode == AddressingMode.Accumulator) Accumulator = value; else { Memory.WriteValue(memoryAddress, (byte)value); } }
/// <summary> /// The ASL - Shift Left One Bit (Memory or Accumulator) /// </summary> /// <param name="addressingMode">The addressing Mode being used</param> public void ASlOperation(AddressingMode addressingMode) { int value; var memoryAddress = 0; if (addressingMode == AddressingMode.Accumulator) value = Accumulator; else { memoryAddress = GetAddressByAddressingMode(addressingMode); value = Memory.ReadValue(memoryAddress); } //If the 7th bit is set, then we have a carry CarryFlag = ((value & 0x80) != 0); value = (value << 1); if (value > 255) value -= 256; SetIsSignNegative(value); SetIsResultZero(value); if (addressingMode == AddressingMode.Accumulator) Accumulator = value; else { Memory.WriteValue(memoryAddress, (byte)value); } }
/// <summary> /// The Or Operation. Performs an Or Operation with the accumulator and a value in memory /// </summary> /// <param name="addressingMode">The addressing mode to use</param> private void OrOperation(AddressingMode addressingMode) { Accumulator = Accumulator | Memory.ReadValue(GetAddressByAddressingMode(addressingMode)); SetNegativeFlag(Accumulator); SetZeroFlag(Accumulator); }
/// <summary> /// The AND - Compare Memory with Accumulator operation /// </summary> /// <param name="addressingMode">The addressing mode being used</param> private void AndOperation(AddressingMode addressingMode) { Accumulator = Memory.ReadValue(GetAddressByAddressingMode(addressingMode)) & Accumulator; SetIsResultZero(Accumulator); SetIsSignNegative(Accumulator); }
/// <summary> /// The ROL operation. Performs a rotate left operation on a value in memory. /// </summary> /// <param name="addressingMode">The addressing mode to use</param> private void RolOperation(AddressingMode addressingMode) { int value; var memoryAddress = 0; if (addressingMode == AddressingMode.Accumulator) value = Accumulator; else { memoryAddress = GetAddressByAddressingMode(addressingMode); value = Memory.ReadValue(memoryAddress); } //Store the carry flag before shifting it var newCarry = (0x80 & value) != 0; //The And here ensures that if the value is greater than 255 it wraps properly. value = (value << 1) & 0xFE; if (CarryFlag) value = value | 0x01; CarryFlag = newCarry; SetZeroFlag(value); SetNegativeFlag(value); if (addressingMode == AddressingMode.Accumulator) Accumulator = value; else { Memory.WriteValue(memoryAddress, (byte)value); } }
public virtual int CyclesFor(AddressingMode mode) { return numberOfCycles[mode]; }
/// <summary> /// The ROR operation. Performs a rotate right operation on a value in memory. /// </summary> /// <param name="addressingMode">The addressing mode to use</param> private void RorOperation(AddressingMode addressingMode) { int value; var memoryAddress = 0; if (addressingMode == AddressingMode.Accumulator) value = Accumulator; else { memoryAddress = GetAddressByAddressingMode(addressingMode); value = Memory.ReadValue(memoryAddress); } //Store the carry flag before shifting it var newCarry = (0x01 & value) != 0; value = (value >> 1); //If the carry flag is set then 0x if (CarryFlag) value = value | 0x80; CarryFlag = newCarry; SetZeroFlag(value); SetNegativeFlag(value); if (addressingMode == AddressingMode.Accumulator) Accumulator = value; else { Memory.WriteValue(memoryAddress, (byte)value); } }