private static void InstructionHandler(Match lineReg) { string opcode = lineReg.Groups["opcode"].Value; string operands = lineReg.Groups["operands"].Value; if (macros.ContainsKey(opcode)) { Match macroReg = Regex.Match($"{opcode} {operands}", CPUDef.macroReg); CallMacroHandler(macroReg); return; } string label = lineReg.Groups["label"].Value; ushort opcodeAddr = currentAddr; opcode = lineReg.Groups["opcode"].Value.ToUpper(); if (!string.IsNullOrWhiteSpace(label)) { Symbol lSymb = new Symbol { Type = SymbolType.WORD, Value = currentAddr }; AddSymbol(label, lSymb); } Byte[] addrModesValues = CPUDef.OPC_TABLE[opcode]; CPUDef.AddrModes addrMode = CPUDef.AddrModes.NO; List <byte> instBytes = new List <byte>(); CPUDef.InstructionInfo instInfo = new CPUDef.InstructionInfo(); bool syntaxError = true; if (string.IsNullOrWhiteSpace(operands)) { syntaxError = false; // 1 byte opcode if (Array.Exists(CPUDef.ACC_OPC, opc => opc.Equals(opcode))) { addrMode = CPUDef.AddrModes.ACC; } else { addrMode = CPUDef.AddrModes.IMP; } instInfo = new CPUDef.InstructionInfo { addrMode = addrMode, nbrBytes = 1 }; instBytes.Add(addrModesValues[(int)addrMode]); } else { string expr = string.Empty; // 2 bytes opcode if (Array.Exists(CPUDef.REL_OPC, opc => opc.Equals(opcode))) { syntaxError = false; expr = operands; instInfo = new CPUDef.InstructionInfo { addrMode = CPUDef.AddrModes.REL, nbrBytes = 2 }; } else { instInfo = CPUDef.GetInstructionInfo(operands); syntaxError = false; expr = instInfo.expr; } if (syntaxError) { AddError(Errors.OPERANDS); } else { addrMode = instInfo.addrMode; ExprResult exprRes = ResolveExpr(expr, addrMode); if (exprRes.undefinedSymbs.Count == 0) { // convert to zero page if symbol is a single byte if (CPUDef.isAbsoluteAddr(addrMode) && exprRes.Type == SymbolType.BYTE) { addrMode = addrMode + 3; instInfo.nbrBytes = 2; } instBytes.Add(addrModesValues[(int)addrMode]); if (instInfo.nbrBytes == 2) { instBytes.Add((byte)exprRes.Result); } else { instBytes.AddRange(GetWordBytes((ushort)exprRes.Result)); } } else { instBytes.Add(addrModesValues[(int)addrMode]); SymbolType typeExpr; if (instInfo.nbrBytes == 2) { instBytes.AddRange(new byte[1] { 0 }); typeExpr = SymbolType.BYTE; } else // 3 bytes instr { instBytes.AddRange(new byte[2] { 0, 0 }); typeExpr = SymbolType.WORD; } ushort position = (ushort)(opcodeAddr - originAddr + 1); UnresolvedExpr exprObj = new UnresolvedExpr { Position = position, Type = typeExpr, addrMode = addrMode, NbrUndefinedSymb = exprRes.undefinedSymbs.Count, Expr = expr }; unsolvedExprList.Add(position, exprObj); foreach (string symb in exprRes.undefinedSymbs) { UnresolvedSymbol unResSymb = new UnresolvedSymbol(); unResSymb.DependingList = new List <string>(); unResSymb.ExprList = new List <ushort>(); unResSymb.ExprList.Add(position); AddUnsolvedSymbol(symb, unResSymb); } } } } if (!syntaxError) { currentAddr += instInfo.nbrBytes; fileOutMemory.AddRange(instBytes.ToArray()); MainConsole.WriteLine($"{opcode} mode {addrMode.ToString()}"); } }
private static ExprResult ResolveExpr(string exprIn, CPUDef.AddrModes addrMode = CPUDef.AddrModes.NO, bool isLogical = false) { List <Token> tokens = Tokenizer.Tokenize(exprIn); string expr = string.Empty; Symbol symb; ExprResult exprRes = new ExprResult(); exprRes.undefinedSymbs = new List <string>(); foreach (Token token in tokens) { switch (token.Type) { case "HB": expr = $"{expr} {Byte.Parse(token.Value, NumberStyles.HexNumber)}"; break; case "HW": expr = $"{expr} {ushort.Parse(token.Value, NumberStyles.HexNumber)}"; break; case "binByte": expr = $"{expr} {Convert.ToByte(token.Value, 2)}"; break; case "DEC": int val = int.Parse(token.Value); if (val <= 255) { expr = $"{expr} {(byte)val}"; } else { expr = $"{expr} {(ushort)val}"; } break; case "label": symb = GetSymbolValue(token.Value); if (symb != null) { expr = $"{expr} {symb.Value}"; } else { exprRes.undefinedSymbs.Add(token.Value); } break; case "loLabel": symb = GetSymbolValue(token.Value); if (symb != null) { expr = $"{expr} {GetLowByte((ushort)symb.Value)}"; } else { exprRes.undefinedSymbs.Add(token.Value); } break; case "hiLabel": symb = GetSymbolValue(token.Value); if (symb != null) { expr = $"{expr} {GetHighByte((ushort)symb.Value)}"; } else { exprRes.undefinedSymbs.Add(token.Value); } break; case "loHW": expr = $"{expr} {GetLowByte(ushort.Parse(token.Value, NumberStyles.HexNumber))}"; break; case "hiHW": expr = $"{expr} {GetHighByte(ushort.Parse(token.Value, NumberStyles.HexNumber))}"; break; default: expr = $"{expr} {token.Value}"; break; } } if (exprRes.undefinedSymbs.Count == 0) { if (isLogical) { exprRes.Result = EvaluateLogicalExpression(expr); } else { DataTable dt = new DataTable(); exprRes.Result = dt.Compute(expr, ""); exprRes.Type = exprRes.Result <= 255 ? SymbolType.BYTE : SymbolType.WORD; if (addrMode == CPUDef.AddrModes.REL && exprRes.Type == SymbolType.WORD) { int delta = (ushort)exprRes.Result - (currentAddr + 1); byte res; if (delta > 127 || delta < -128) { AddError(Errors.REL_JUMP); } else { if (delta < 0) { res = (byte)(255 + delta); } else { res = (byte)(delta - 1); } exprRes.Result = res; exprRes.Type = SymbolType.BYTE; } } } } return(exprRes); }