/// <summary> /// Returns a value between 0 and 255, or -1 if no opcode was found, or -2 if the addressing mode is not available for the instruction.. /// </summary> /// <param name="instruction"></param> /// <param name="addressing"></param> /// <returns></returns> private int FindOpcode(StringSection instruction, Opcode.addressing addressing) { var ops = Opcode.allOps; bool instructionFound = false; bool foundInstructionInvalid = false; for (int i = 0; i < Opcode.allOps.Length; i++) { if (StringEquals(ops[i].name, instruction, true)) { // Note that the instruction exists. We need to tell the user whether // an instruction does not exist or the desired addressing mode is not available. instructionFound = true; var addrMode = ops[i].addressing; // Branch instructions will be treated as absolute until they are actually encoded. if (addrMode == Opcode.addressing.relative) { addrMode = Opcode.addressing.absolute; } if (addressing == addrMode) { if (ops[i].valid | Assembler.AllowInvalidOpcodes) { return(i); } else { foundInstructionInvalid = true; } } } } if (instructionFound) { if (foundInstructionInvalid) { return((int)OpcodeError.InvalidOpcode); } else { return((int)OpcodeError.InvalidAddressing); } } else { return((int)OpcodeError.UnknownInstruction); } }
private bool TryZeroPageEqivalent(ref Opcode.addressing addressing) { switch (addressing) { case Opcode.addressing.absolute: addressing = Opcode.addressing.zeropage; return(true); case Opcode.addressing.absoluteIndexedX: addressing = Opcode.addressing.zeropageIndexedX; return(true); case Opcode.addressing.absoluteIndexedY: addressing = Opcode.addressing.zeropageIndexedY; return(true); default: return(false); } }
private bool IsZeroPage(Opcode.addressing addressing) { switch (addressing) { case Opcode.addressing.zeropage: case Opcode.addressing.zeropageIndexedX: case Opcode.addressing.zeropageIndexedY: return(true); case Opcode.addressing.implied: case Opcode.addressing.immediate: case Opcode.addressing.absolute: case Opcode.addressing.indirect: case Opcode.addressing.indirectX: case Opcode.addressing.indirectY: case Opcode.addressing.relative: case Opcode.addressing.absoluteIndexedX: case Opcode.addressing.absoluteIndexedY: default: return(false); } }
private static void SetOpcodeError(int sourceLine, string instructionString, Opcode.addressing addressing, int opcodeVal, out Error error) { var errorCode = (OpcodeError)opcodeVal; switch (errorCode) { case OpcodeError.UnknownInstruction: error = new Error(ErrorCode.Invalid_Instruction, Error.Msg_InstructionUndefined, sourceLine); break; case OpcodeError.InvalidAddressing: error = new Error(ErrorCode.Invalid_Instruction, Error.Msg_InstructionBadAddressing, sourceLine); break; case OpcodeError.InvalidOpcode: error = new Error(ErrorCode.Invalid_Instruction, Error.Msg_OpcodeInvalid, sourceLine); break; default: System.Diagnostics.Debug.Fail("Unexpected error."); error = new Error(ErrorCode.Engine_Error, Error.Msg_Engine_InvalidState); break; } }
// Todo: Move TryToConvertToZeroPage and FindOpcode to another class, probably assembler. // (The only reason they need to be instance methods is for AllowInvalidOpcodes, but this // could also be specified as a parameter). public bool TryToConvertToZeroPage(ref ParsedInstruction instruction) { var op = Opcode.allOps[instruction.opcode]; var addressing = op.addressing; Opcode.addressing newAddressing = addressing; switch (addressing) { case Opcode.addressing.absolute: newAddressing = Opcode.addressing.zeropage; break; case Opcode.addressing.absoluteIndexedX: newAddressing = Opcode.addressing.zeropageIndexedX; break; case Opcode.addressing.absoluteIndexedY: newAddressing = Opcode.addressing.zeropageIndexedY; break; } if (addressing == newAddressing) { return(false); } int newOpcode = FindOpcode(op.name, newAddressing); if (newOpcode >= 0) { instruction = new ParsedInstruction(instruction, (byte)newOpcode); return(true); } return(false); }