public Symbol(string name, EnSection section, int address, EnFlag flag = EnFlag.None) { Name = name; Section = section; Address = address; Flag = flag; }
void AssembleLine(string line) { string[] tokens = line.Split(Seperator, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 0) { return; } string op = tokens[0]; string p1Str = ""; Int32 p1 = 0; bool isP1Int = false; bool isP1Exists = (tokens.Length > 1); if (isP1Exists) { p1Str = tokens[1]; isP1Int = Int32.TryParse(p1Str, out p1); } if (op.StartsWith("CNST")) { if (isP1Int) { mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Immediate, OpModifier.Empty, p1)); } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op == "ADDRLP4") { if (isP1Exists) { int val = 0; if (isP1Int) { val = p1; } else { if (p1Str.Contains("+")) { string[] values = p1Str.Split(new string[] { "+" }, StringSplitOptions.RemoveEmptyEntries); if (values.Length == 2) { int v1 = 0; int v2 = 0; bool success = Int32.TryParse(values[0], out v1); if (!success) { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } success = Int32.TryParse(values[1], out v2); if (!success) { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } val = v1 + v2; } else { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } } else if (p1Str.Contains("-")) { string[] values = p1Str.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries); if (values.Length == 2) { int v1 = 0; int v2 = 0; bool success = Int32.TryParse(values[0], out v1); if (!success) { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } success = Int32.TryParse(values[1], out v2); if (!success) { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } val = v1 - v2; } else { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } } } mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Register, OpModifier.Register, (int)Register.Alp1, (int)Register.BasePointer)); mInstructions.Add(new Instruction(OpCode.ADD, OpModifier.Register, OpModifier.Immediate, (int)Register.Alp1, val + 4 + mCurrentFunction.ArgumentsCallDataSize)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op == "ADDRFP4") { if (isP1Int) { mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Register, OpModifier.MemoryAtRegister, (int)Register.Alp1, (int)Register.BasePointer)); //Going to previous stack frame, because LCC bytecode assumes args are there mInstructions.Add(new Instruction(OpCode.ADD, OpModifier.Register, OpModifier.Immediate, (int)Register.Alp1, p1 + 4)); //0 is previous of previous function's ebp value, so args start from +4 mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op == "ADDRGP4") { if (isP1Exists) { if (p1Str.Contains("+")) { string[] values = p1Str.Split(new string[] { "+" }, StringSplitOptions.RemoveEmptyEntries); if (values.Length == 2) { string symbol = values[0]; int v2 = 0; bool success = Int32.TryParse(values[1], out v2); if (!success) { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } mSymbolUseList.Add(new SymbolUsage(symbol, EnSection.Code, mInstructions.Count)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Immediate, OpModifier.Empty, 0)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp5)); mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Register, OpModifier.Immediate, (int)Register.Alp6, v2)); mInstructions.Add(new Instruction(OpCode.ADD, OpModifier.Register, OpModifier.Register, (int)Register.Alp5, (int)Register.Alp6)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp5)); } else { throw new Exception(string.Format("{0} not understood: {1}", op, p1Str)); } } else { string label = p1Str; mSymbolUseList.Add(new SymbolUsage(label, EnSection.Code, mInstructions.Count)); Instruction ins = new Instruction(OpCode.PUSH, OpModifier.Immediate, OpModifier.Empty, 0); mInstructions.Add(ins); } } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("ARG")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); //mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Memory | OpModifier.BpOffset, OpModifier.Register, mCurrentArgSize + 4, (int)Register.Alp1)); mCurrentArgSize += 4; } else if (op == "ASGNB") { if (isP1Int) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.SET_COUNTER, OpModifier.Immediate, OpModifier.Empty, p1)); mInstructions.Add(new Instruction(OpCode.COPY_MEMORY_ARRAY, OpModifier.Register, OpModifier.Register, (int)Register.Alp2, (int)Register.Alp1)); } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op.StartsWith("ASGN")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(4)); mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.MemoryAtRegister | dataType, OpModifier.Register, (int)Register.Alp2, (int)Register.Alp1)); } else if (op == "INDIRB") { //Do nothing. We have address already on top of stack. } else if (op.StartsWith("INDIR")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Register, OpModifier.MemoryAtRegister, (int)Register.Alp2, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); } else if (op.StartsWith("LABEL")) { if (isP1Exists) { if (mSymbols.ContainsKey(p1Str)) { throw new Exception(string.Format("LABEL {0} already defined", p1Str)); } if (mCurrentSection == EnSection.Code) { //mSymbolsForCode.Add(p1Str, mInstructions.Count); mSymbols.Add(p1Str, new Symbol(p1Str, EnSection.Code, mInstructions.Count)); } else if (mCurrentSection == EnSection.Data) { int dataIndex = mData.Count; if (mCurrentAlign > 1) { int mod = dataIndex % (int)mCurrentAlign; if (mod != 0) { //Align to mCurrentAlign byte boundry int bytesNeeded = (int)mCurrentAlign - mod; for (int i = 0; i < bytesNeeded; ++i) { mData.Add(0);//Fill bytesNeeded bytes } dataIndex = mData.Count; } } //mSymbolsForData.Add(p1Str, dataIndex); mSymbols.Add(p1Str, new Symbol(p1Str, EnSection.Data, dataIndex)); } else if (mCurrentSection == EnSection.Lit) { int dataIndex = mLit.Count; if (mCurrentAlign > 1) { int mod = dataIndex % (int)mCurrentAlign; if (mod != 0) { //Align to mCurrentAlign byte boundry int bytesNeeded = (int)mCurrentAlign - mod; for (int i = 0; i < bytesNeeded; ++i) { mLit.Add(0);//Fill bytesNeeded bytes } dataIndex = mLit.Count; } } //mSymbolsForLit.Add(p1Str, dataIndex); mSymbols.Add(p1Str, new Symbol(p1Str, EnSection.Lit, dataIndex)); } else if (mCurrentSection == EnSection.Bss) { int dataIndex = mBss; if (mCurrentAlign > 1) { int mod = dataIndex % (int)mCurrentAlign; if (mod != 0) { //Align to mCurrentAlign byte boundry int bytesNeeded = (int)mCurrentAlign - mod; mBss += bytesNeeded; dataIndex = mBss; } } //mSymbolsForBss.Add(p1Str, dataIndex); mSymbols.Add(p1Str, new Symbol(p1Str, EnSection.Bss, dataIndex)); } } else { throw new Exception(string.Format("LABEL needs a parameter")); } } else if (op.StartsWith("ADD")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.ADD, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("SUB")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.SUB, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("MUL")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.MUL, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("DIV")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.DIV, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("MOD")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.MOD, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("LSH")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.SHIFTLEFT, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("RSH")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.SHIFTRIGHT, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("BAND")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.BITWISE_AND, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("BCOM")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.BITWISE_COMPLEMENT, OpModifier.Register | dataType, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("BOR")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.BITWISE_OR, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("BXOR")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.BITWISE_XOR, OpModifier.Register | dataType, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("CVF")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.CONVERT, OpModifier.Register | OpModifier.DataTypeF4, OpModifier.Register | dataType, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("CVI")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.CONVERT, OpModifier.Register | OpModifier.DataTypeI4, OpModifier.Register | dataType, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("CVU")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.CONVERT, OpModifier.Register | OpModifier.DataTypeU4, OpModifier.Register | dataType, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("CVP")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); mInstructions.Add(new Instruction(OpCode.CONVERT, OpModifier.Register | OpModifier.DataTypeU4, OpModifier.Register | dataType, (int)Register.Alp1, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("JUMP")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1));//Address for JUMP is in Alp1 mInstructions.Add(new Instruction(OpCode.JUMP, OpModifier.Register | OpModifier.Absolute, OpModifier.Empty, (int)Register.Alp1)); } else if (op.StartsWith("EQ")) { if (isP1Exists) { string label = p1Str; OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); EmitConditionalJump(OpCode.JUMPIF_EQ, label, dataType); } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("NE")) { if (isP1Exists) { string label = p1Str; OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); EmitConditionalJump(OpCode.JUMPIF_NEQ, label, dataType); } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("LE")) { if (isP1Exists) { string label = p1Str; OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); EmitConditionalJump(OpCode.JUMPIF_LTE, label, dataType); } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("LT")) { if (isP1Exists) { string label = p1Str; OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); EmitConditionalJump(OpCode.JUMPIF_LT, label, dataType); } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("GE")) { if (isP1Exists) { string label = p1Str; OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); EmitConditionalJump(OpCode.JUMPIF_GTE, label, dataType); } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("GT")) { if (isP1Exists) { string label = p1Str; OpModifier dataType = ConvertStringToOpModifierDataType(op.Substring(op.Length - 2)); EmitConditionalJump(OpCode.JUMPIF_GT, label, dataType); } else { throw new Exception(string.Format("{0} needs label parameter", op)); } } else if (op.StartsWith("CALL")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1));//Address for CALL is in Alp1 /* * if (mCurrentArgSize > 0) * { * mInstructions.Add(new Instruction(OpCode.REVERSE_STACK, OpModifier.Immediate, OpModifier.Immediate, 0, mCurrentArgSize / 4)); * }*/ mInstructions.Add(new Instruction(OpCode.CALL, OpModifier.Register | OpModifier.Absolute, OpModifier.Empty, (int)Register.Alp1)); //mInstructions.Add(new Instruction(OpCode.DEC_SP, OpModifier.Immediate, OpModifier.Empty, mCurrentArgSize));//Cleanup mCurrentArgSize = 0; //We assume, we have put return value to Return register. So we should push it here. mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (Int32)Register.Return)); } else if (op.StartsWith("RET")) { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Return)); } else if (op.StartsWith("proc")) { if (tokens.Length > 3) { string functionName = p1Str; Int32 localSize = Int32.Parse(tokens[2]); Int32 argSize = Int32.Parse(tokens[3]); if (mFunctions.ContainsKey(functionName)) { throw new Exception(string.Format("Function {0} already exists", functionName)); } else { if (null != mCurrentFunction) { throw new Exception(string.Format("Already inside a function, found a new function: {0}", functionName)); } mCurrentFunction = new Function(functionName, mInstructions.Count, localSize, argSize); mFunctions.Add(functionName, mCurrentFunction); if (mSymbols.ContainsKey(functionName)) { throw new Exception(string.Format("Symbol already defined: {0}", functionName)); } else { mSymbols.Add(functionName, new Symbol(functionName, EnSection.Code, mInstructions.Count)); } } //Prolog mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (Int32)Register.BasePointer)); mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Register, OpModifier.Register, (Int32)Register.BasePointer, (Int32)Register.StackPointer)); mInstructions.Add(new Instruction(OpCode.INC_SP, OpModifier.Immediate, OpModifier.Empty, localSize + argSize)); //TODO:Save registers here (excluding BS, SP) } else { throw new Exception(string.Format("{0} needs two parameters", op)); } } else if (op.StartsWith("endproc")) { if (tokens.Length > 3) { string functionName = p1Str; Int32 localSize = Int32.Parse(tokens[2]); Int32 argSize = Int32.Parse(tokens[3]); if (null == mCurrentFunction) { throw new Exception(string.Format("Not in a function, found end of function", functionName)); } mCurrentFunction = null; //TODO:Restore registers here (excluding BS, SP) //Epilog mInstructions.Add(new Instruction(OpCode.ASSIGN, OpModifier.Register, OpModifier.Register, (Int32)Register.StackPointer, (Int32)Register.BasePointer)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (Int32)Register.BasePointer)); /* * if (IsInterruptHandler) * { * AddInstruction(EnOpCode.OC_IRET); * } * else * { * AddInstruction(EnOpCode.OC_RET); * }*/ mInstructions.Add(new Instruction(OpCode.RET)); } else { throw new Exception(string.Format("{0} needs two parameters", op)); } } else if (op == "export") { if (!mExports.Contains(p1Str)) { mExports.Add(p1Str); } } else if (op == "code") { mCurrentSection = EnSection.Code; } else if (op == "data") { mCurrentSection = EnSection.Data; } else if (op == "bss") { mCurrentSection = EnSection.Bss; } else if (op == "lit") { mCurrentSection = EnSection.Lit; } else if (op == "align") { if (isP1Int) { mCurrentAlign = (UInt32)p1; } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op == "skip") { if (isP1Int) { if (mCurrentSection != EnSection.Bss) { throw new Exception("Encountered a skip in non-bss section"); } else { mBss += p1; } } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op == "byte") { if (isP1Int) { Int32 p2 = 0; bool isP2Int = false; bool isP2Exists = (tokens.Length > 2); if (isP2Exists) { string p2Str = tokens[2]; isP2Int = Int32.TryParse(p2Str, out p2); } if (isP2Int) { List <byte> target = null; if (mCurrentSection == EnSection.Data) { target = mData; } else if (mCurrentSection == EnSection.Lit) { target = mLit; } else { throw new Exception("Unknown section while parsing byte"); } if (null != target) { switch (p1) { case 1: target.Add((byte)(p2 & 0x000000FF)); break; case 2: { target.Add((byte)(p2 & 0x000000FF)); target.Add((byte)((p2 & 0x0000FF00) >> 8)); } break; case 4: { target.Add((byte)(p2 & 0x000000FF)); target.Add((byte)((p2 & 0x0000FF00) >> 8)); target.Add((byte)((p2 & 0x00FF0000) >> 16)); target.Add((byte)((p2 & 0xFF000000) >> 24)); } break; } } } else { throw new Exception(string.Format("{0} needs two integer parameters", op)); } } else { throw new Exception(string.Format("{0} needs two integer parameters", op)); } } else if (op == "address") { if (isP1Exists) { string label = p1Str; if (mCurrentSection != EnSection.Data) { throw new Exception("Encountered 'address' in non-data section"); } else { mSymbolUseList.Add(new SymbolUsage(label, EnSection.Data, mData.Count)); //These 4 bytes will be filled with address of the label when linking mData.Add(0); mData.Add(0); mData.Add(0); mData.Add(0); } } else { throw new Exception(string.Format("{0} needs parameter", op)); } } else if (op == "import") { if (!mImports.Contains(p1Str)) { mImports.Add(p1Str); } } else if (op == "_SETCOUNTER") { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.SET_COUNTER, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op == "_READCOUNTER") { mInstructions.Add(new Instruction(OpCode.READ_COUNTER, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.PUSH, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); } else if (op == "_MEMSET") { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp2)); mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Register, OpModifier.Empty, (int)Register.Alp1)); mInstructions.Add(new Instruction(OpCode.SET_MEMORY_ARRAY, OpModifier.Register, OpModifier.Register, (int)Register.Alp1, (int)Register.Alp2)); } else if (op == "_POP") { mInstructions.Add(new Instruction(OpCode.POP, OpModifier.Empty, OpModifier.Empty)); } else { throw new Exception(string.Format("{0} not implemented", op)); } }
public SymbolUsage(string name, EnSection section, int address) { Name = name; Section = section; Address = address; }