private static Statement ExpandComplex(Statement s) { if(s is Instruction) { Instruction src = s as Instruction; // TODO: is it complex? Instruction dest = new Instruction(); dest.op = src.op.ToLower(); dest.srca = src.srca; dest.srcb = src.srcb; dest.dest = src.dest; return dest; } return s; }
private static void ExpandComplex(Statement s, List<Statement> next_pass) { if(s is Instruction) { Instruction src = s as Instruction; string op_lower = src.op.ToLower(); // is it complex? if (op_lower == "jl") { /* Jump with link add PC, 4->LR j x */ Instruction new_1 = new Instruction(); new_1.cond = src.cond; new_1.op = "add"; new_1.srca = new RegisterOperand { val = "PC" }; new_1.srcb = new IntegerOperand { val = 4 }; new_1.dest = new RegisterOperand { val = "LR" }; next_pass.Add(new_1); Instruction new_2 = new Instruction(); new_2.cond = src.cond; new_2.op = "j"; new_2.srca = src.srca; next_pass.Add(new_2); } else if (op_lower == "jrel") { /* Relative jump only valid if srca is a label/integer -> mov x -> pc (which is interpreted as an add to pc) */ Expression new_srca = null; if (src.srca is IntegerOperand) new_srca = src.srca; else if (src.srca is LabelExpression) { new_srca = src.srca; ((LabelExpression)new_srca).addend = -4; ((LabelExpression)new_srca).is_pcrel = true; } else if (src.srca is RegisterOperand) { var r_srca = src.srca as RegisterOperand; if (regs.ContainsKey(r_srca.val.ToUpper())) { throw new Exception("jrel must have an integer or label operand"); } new_srca = src.srca; ((LabelExpression)new_srca).addend = -4; ((LabelExpression)new_srca).is_pcrel = true; } Instruction new_1 = new Instruction(); new_1.cond = src.cond; new_1.op = "mov"; new_1.srca = new_srca; new_1.dest = new RegisterOperand { val = "PC" }; next_pass.Add(new_1); } else if (op_lower == "jlrel") { /* Relative jump with link only valid if srca is a label/integer -> add pc, 4 -> lr mov x -> pc (which is interpreted as an add to pc) */ Expression new_srca = null; if (src.srca is IntegerOperand) new_srca = src.srca; else if (src.srca is LabelExpression) { new_srca = src.srca; ((LabelExpression)new_srca).addend = -4; ((LabelExpression)new_srca).is_pcrel = true; } else if (src.srca is RegisterOperand) { var r_srca = src.srca as RegisterOperand; if (regs.ContainsKey(r_srca.val.ToUpper())) { throw new Exception("jrel must have an integer or label operand"); } new_srca = src.srca; ((LabelExpression)new_srca).addend = -4; ((LabelExpression)new_srca).is_pcrel = true; } Instruction new_1 = new Instruction(); new_1.cond = src.cond; new_1.op = "add"; new_1.srca = new RegisterOperand { val = "PC" }; new_1.srcb = new IntegerOperand { val = 4 }; new_1.dest = new RegisterOperand { val = "LR" }; next_pass.Add(new_1); Instruction new_2 = new Instruction(); new_2.cond = src.cond; new_2.op = "mov"; new_2.srca = new_srca; new_2.dest = new RegisterOperand { val = "PC" }; next_pass.Add(new_2); } else if (op_lower == "ret") { /* Return j LR */ Instruction new_1 = new Instruction(); new_1.cond = src.cond; new_1.op = "j"; new_1.srca = new RegisterOperand { val = "LR" }; next_pass.Add(new_1); } else if (op_lower == "push") { /* Push x sub SP, 4 -> SP store x, 4 -> SP */ Instruction new_1 = new Instruction(); new_1.cond = src.cond; new_1.op = "sub"; new_1.srca = new RegisterOperand { val = "SP" }; new_1.srcb = new IntegerOperand { val = 4 }; new_1.dest = new RegisterOperand { val = "SP" }; next_pass.Add(new_1); Instruction new_2 = new Instruction(); new_2.cond = src.cond; new_2.op = "store"; new_2.srca = src.srca; new_2.srcb = new IntegerOperand { val = 4 }; new_2.dest = new RegisterOperand { val = "SP" }; next_pass.Add(new_2); } else if (op_lower == "pop") { /* Pop x load SP, 4 -> x add SP, 4 -> SP */ Instruction new_1 = new Instruction(); new_1.cond = src.cond; new_1.op = "load"; new_1.srca = new RegisterOperand { val = "SP" }; new_1.srcb = new IntegerOperand { val = 4 }; new_1.dest = src.srca; next_pass.Add(new_1); Instruction new_2 = new Instruction(); new_2.cond = src.cond; new_2.op = "add"; new_2.srca = new RegisterOperand { val = "SP" }; new_2.srcb = new IntegerOperand { val = 4 }; new_2.dest = new RegisterOperand { val = "SP" }; next_pass.Add(new_2); } else { Instruction dest = new Instruction(); dest.op = op_lower; dest.srca = src.srca; dest.srcb = src.srcb; dest.dest = src.dest; dest.cond = src.cond; next_pass.Add(dest); } } else next_pass.Add(s); }