private static void VectorMatchSplit(VectorMatch vm) { int tempofset = vm.Offset; string[] calcs = new string[vm.Count]; string[] rcalcs = new string[vm.Count]; //Generate calcs and rcalcs for (int i = 0; i < vm.Count; i++) { calcs[i] = ParseScalarCalc(((UnwrappedElement)elements[vm.Start + i]).stuff); rcalcs[i] = ParseScalarCalcWithReg(((UnwrappedElement)elements[vm.Start + i]).stuff); } //Rotate the registers to try and match up rcalcs RotateUnmatchedRegisters(ref rcalcs[0], (UnwrappedElement)elements[vm.Start]); for (int i = 1; i < vm.Count; i++) { if (calcs[i] == calcs[i - 1]) { if (rcalcs[i] != rcalcs[i - 1]) { if (!RotateDeepRegisters(ref rcalcs[i], rcalcs[i - 1], (UnwrappedElement)elements[vm.Start + i])) { RotateUnmatchedRegisters(ref rcalcs[i], (UnwrappedElement)elements[vm.Start + i]); } } } } //Split vectors wherever rcalcs dont match up int start = 0; for (int i = 1; i < vm.Count; i++) { if (rcalcs[i] != rcalcs[i - 1]) { if (i > start + 1) { UnwrappedElement[] o = new UnwrappedElement[i - start + 1]; elements.CopyTo(start + vm.Start, o, 0, i - start + 1); FoundVectors.Add(new VectorMatch(start + vm.Start, i - start + 1, vm.Upward, o, vm.Offset, vm.Reg)); } start = i; Offset = ((UnwrappedElement)elements[i + vm.Start]).Offset; } } if (start < vm.Count - 1) { UnwrappedElement[] o = new UnwrappedElement[vm.Count - start]; elements.CopyTo(start + vm.Start, o, 0, vm.Count - start); FoundVectors.Add(new VectorMatch(start + vm.Start, vm.Count - start, vm.Upward, o, Offset, vm.Reg)); } }
public VectorMatch(VectorMatch vm, int arg, int start, int count, VectorDirection dir) { Offset = vm.Offset + 4 * start;; Reg = vm.Reg; Start = start + vm.Start; Count = count; Upward = vm.Upward; calc = vm.calc; if (dir == VectorDirection.Unknown) { throw new OptimizationException("VectorMatch: Unknown vector direction"); } fpulines = new int[Count][]; for (int i = Start; i < count + Start; i++) { fpulines[i - Start] = ((UnwrappedElement)vectorizer.elements[i]).FpuLines; } arguments = new Element[count][]; Array.Copy(vm.arguments, start, arguments, 0, count); if (vm.pArguments != null) { pArguments = new Vector[vm.pArguments.Length + 1]; vm.pArguments.CopyTo(pArguments, 0); for (int i = 0; i < vm.pArguments.Length - 1; i++) { pArguments[i].Count = count; if (start > 0) { if (pArguments[i].Direction == VectorDirection.Up) { pArguments[i].Offset += 4 * start; } else if (pArguments[i].Direction == VectorDirection.Down) { pArguments[i].Offset -= 4 * start; } } } } else { pArguments = new Vector[1]; } pArguments[arg] = new Vector(arguments[0][arg].Offset, arguments[0][arg].Register, count, dir); }
public VectorMatch(VectorMatch vm,int arg,int start,int count,VectorDirection dir) { Offset=vm.Offset+4*start; ; Reg=vm.Reg; Start=start+vm.Start; Count=count; Upward=vm.Upward; calc=vm.calc; if(dir==VectorDirection.Unknown) throw new OptimizationException("VectorMatch: Unknown vector direction"); fpulines=new int[Count][]; for(int i=Start;i<count+Start;i++) { fpulines[i-Start]=((UnwrappedElement)vectorizer.elements[i]).FpuLines; } arguments=new Element[count][]; Array.Copy(vm.arguments,start,arguments,0,count); if(vm.pArguments!=null) { pArguments=new Vector[vm.pArguments.Length+1]; vm.pArguments.CopyTo(pArguments,0); for(int i=0;i<vm.pArguments.Length-1;i++) { pArguments[i].Count=count; if(start>0) { if(pArguments[i].Direction==VectorDirection.Up) { pArguments[i].Offset+=4*start; } else if(pArguments[i].Direction==VectorDirection.Down) { pArguments[i].Offset-=4*start; } } } } else { pArguments=new Vector[1]; } pArguments[arg]=new Vector(arguments[0][arg].Offset,arguments[0][arg].Register,count,dir); }
private static void VectorMatchSplit(VectorMatch vm) { int tempofset=vm.Offset; string[] calcs=new string[vm.Count]; string[] rcalcs=new string[vm.Count]; //Generate calcs and rcalcs for(int i=0;i<vm.Count;i++) { calcs[i]=ParseScalarCalc(((UnwrappedElement)elements[vm.Start+i]).stuff); rcalcs[i]=ParseScalarCalcWithReg(((UnwrappedElement)elements[vm.Start+i]).stuff); } //Rotate the registers to try and match up rcalcs RotateUnmatchedRegisters(ref rcalcs[0],(UnwrappedElement)elements[vm.Start]); for(int i=1;i<vm.Count;i++) { if(calcs[i]==calcs[i-1]) { if(rcalcs[i]!=rcalcs[i-1]) { if(!RotateDeepRegisters(ref rcalcs[i],rcalcs[i-1],(UnwrappedElement)elements[vm.Start+i])) { RotateUnmatchedRegisters(ref rcalcs[i],(UnwrappedElement)elements[vm.Start+i]); } } } } //Split vectors wherever rcalcs dont match up int start=0; for(int i=1;i<vm.Count;i++) { if(rcalcs[i]!=rcalcs[i-1]) { if(i>start+1) { UnwrappedElement[] o=new UnwrappedElement[i-start+1]; elements.CopyTo(start+vm.Start,o,0,i-start+1); FoundVectors.Add(new VectorMatch(start+vm.Start,i-start+1,vm.Upward,o,vm.Offset,vm.Reg)); } start=i; Offset=((UnwrappedElement)elements[i+vm.Start]).Offset; } } if(start<vm.Count-1) { UnwrappedElement[] o=new UnwrappedElement[vm.Count-start]; elements.CopyTo(start+vm.Start,o,0,vm.Count-start); FoundVectors.Add(new VectorMatch(start+vm.Start,vm.Count-start,vm.Upward,o,Offset,vm.Reg)); } }
private static VectorMatch[] ProcessSplit(VectorMatch vm,int arg) { int Offset=-1; int ExpectedOffset=-1; string Reg=""; int VectorStart=0; VectorDirection dir=VectorDirection.Unknown; ArrayList matches=new ArrayList(); for(int i=0;i<vm.arguments.Length;i++) { if(i==0||Offset==-1) { Offset=vm.arguments[i][arg].Offset; Reg=vm.arguments[i][arg].Register; VectorStart=i; } else if(ExpectedOffset==-1) { if(vm.arguments[i][arg].Register==Reg&&vm.arguments[i][arg].Offset==Offset+4) { ExpectedOffset=vm.arguments[i][arg].Offset+4; dir=VectorDirection.Up; } else if(vm.arguments[i][arg].Register==Reg&&vm.arguments[i][arg].Offset==Offset-4) { ExpectedOffset=vm.arguments[i][arg].Offset-4; dir=VectorDirection.Down; } else if(vm.arguments[i][arg].Register==Reg&&vm.arguments[i][arg].Offset==Offset) { ExpectedOffset=vm.arguments[i][arg].Offset; dir=VectorDirection.Static; } else { Offset=vm.arguments[i][arg].Offset; VectorStart=i; Reg=vm.arguments[i][arg].Register; ExpectedOffset=-1; } } else { if((!(i-VectorStart==4))&&vm.arguments[i][arg].Register==Reg&&ExpectedOffset==vm.arguments[i][arg].Offset) { if(dir==VectorDirection.Up) { ExpectedOffset+=4; } else if(dir==VectorDirection.Down) { ExpectedOffset-=4; } } else { matches.Add(new VectorMatch(vm,arg,VectorStart,i-VectorStart,dir)); Offset=vm.arguments[i][arg].Offset; VectorStart=i; Reg=vm.arguments[i][arg].Register; ExpectedOffset=-1; } } } if(Offset!=-1&&ExpectedOffset!=-1) { matches.Add(new VectorMatch(vm,arg,VectorStart,vm.arguments.Length-VectorStart,dir)); } return (VectorMatch[])matches.ToArray(typeof(VectorMatch)); }
private static VectorMatch[] ProcessSplit(VectorMatch vm, int arg) { int Offset = -1; int ExpectedOffset = -1; string Reg = ""; int VectorStart = 0; VectorDirection dir = VectorDirection.Unknown; ArrayList matches = new ArrayList(); for (int i = 0; i < vm.arguments.Length; i++) { if (i == 0 || Offset == -1) { Offset = vm.arguments[i][arg].Offset; Reg = vm.arguments[i][arg].Register; VectorStart = i; } else if (ExpectedOffset == -1) { if (vm.arguments[i][arg].Register == Reg && vm.arguments[i][arg].Offset == Offset + 4) { ExpectedOffset = vm.arguments[i][arg].Offset + 4; dir = VectorDirection.Up; } else if (vm.arguments[i][arg].Register == Reg && vm.arguments[i][arg].Offset == Offset - 4) { ExpectedOffset = vm.arguments[i][arg].Offset - 4; dir = VectorDirection.Down; } else if (vm.arguments[i][arg].Register == Reg && vm.arguments[i][arg].Offset == Offset) { ExpectedOffset = vm.arguments[i][arg].Offset; dir = VectorDirection.Static; } else { Offset = vm.arguments[i][arg].Offset; VectorStart = i; Reg = vm.arguments[i][arg].Register; ExpectedOffset = -1; } } else { if ((!(i - VectorStart == 4)) && vm.arguments[i][arg].Register == Reg && ExpectedOffset == vm.arguments[i][arg].Offset) { if (dir == VectorDirection.Up) { ExpectedOffset += 4; } else if (dir == VectorDirection.Down) { ExpectedOffset -= 4; } } else { matches.Add(new VectorMatch(vm, arg, VectorStart, i - VectorStart, dir)); Offset = vm.arguments[i][arg].Offset; VectorStart = i; Reg = vm.arguments[i][arg].Register; ExpectedOffset = -1; } } } if (Offset != -1 && ExpectedOffset != -1) { matches.Add(new VectorMatch(vm, arg, VectorStart, vm.arguments.Length - VectorStart, dir)); } return((VectorMatch[])matches.ToArray(typeof(VectorMatch))); }
public static Operation DeepOp(ref VectorMatch vm,byte depth) { if(depth>254) throw new OptimizationException("Code generater: Too deep recursion"); int count=0; int maxcount=0; int pos=0; string s=vm.calc; for(int i=0;i<s.Length;i++) { switch(s[i]) { case '(': count++; if(count>maxcount) maxcount=count; break; case ')': count--; break; } } for(int i=0;i<s.Length;i++) { switch(s[i]) { case '(': count++; if(count==maxcount) { ArgsToUse atu=ArgsToUse.None; int b=2; if(s[i+1]!='$') { atu|=ArgsToUse.Left; b--; } if(s[i+3]!='$') { atu|=ArgsToUse.Right; b--; } Operation o=new Operation(); switch(atu) { case ArgsToUse.None: o=new Operation(vm.pArguments[pos],vm.pArguments[pos+1],s[i+2]); break; case ArgsToUse.Left: o=new Operation(GetRegister(s[i+1]),vm.pArguments[pos],s[i+2]); //Registers[GetRegister(s[i+1])].contains=depth; break; case ArgsToUse.Right: o=new Operation(vm.pArguments[pos],GetRegister(s[i+3]),s[i+2]); break; case ArgsToUse.Both: o=new Operation(GetRegister(s[i+3]),GetRegister(s[i+1]),s[i+2]); //Registers[GetRegister(s[i+1])].contains=depth; break; } Vector[] vs=new Vector[vm.pArguments.Length-b]; int c=0; for(int a=0;a<vm.pArguments.Length;a++) { if(a==c&&b>0) continue; if(a==c+1&&b>1) continue; vs[c++]=vm.pArguments[a]; } vm.pArguments=vs; vm.calc=s.Remove(i,5); vm.calc=vm.calc.Insert(i,""+(char)depth); return o; } break; case ')': count--; break; case '$': pos++; break; } } throw new OptimizationException("Code generater: No operation to perform"); }
public static void v4CreateCode(VectorMatch function) { byte a=0; while(function.calc.Length>1) { Operation op=DeepOp(ref function,a++); if(op.args==ArgsToUse.None) { op.op1loc=v4MoveToRegister(op.op1); op.args=ArgsToUse.Left; } if((op.args&ArgsToUse.Left)==0) { op.op1loc=v4MoveToRegister(op.op1); op.args|=ArgsToUse.Left; } if((op.args&ArgsToUse.Right)==0&&(!aligned||op.op2.Direction!=VectorDirection.Up)) { op.op2loc=v4MoveToRegister(op.op2); op.args|=ArgsToUse.Right; } Registers[op.op1loc].contains=(byte)(a-1); string s=null; switch(op.op) { case '+': s="addps "; break; case '-': s="subps "; break; case '*': s="mulps "; break; case '/': s="divps "; break; } if((op.args&ArgsToUse.Left)==0) { s+="["+op.op1.Register+ToHex(op.op1.Offset)+"],"; } else { s+="xmm"+op.op1loc+","; } if((op.args&ArgsToUse.Right)==0) { s+="["+op.op2.Register+ToHex(op.op2.Offset)+"]"; } else { s+="xmm"+op.op2loc; } AsmFile.WriteLine(s); } if(!function.Upward) { AsmFile.WriteLine("shufps xmm"+(byte)function.calc[0]+",xmm"+GetRegister(function.calc[0])+",0x1B"); } if(aligned) { AsmFile.WriteLine("movaps ["+function.Reg+ToHex(function.Offset)+"],xmm"+GetRegister(function.calc[0])); } else { AsmFile.WriteLine("movups ["+function.Reg+ToHex(function.Offset)+"],xmm"+GetRegister(function.calc[0])); } }
public static void v3CreateCode(VectorMatch function) { byte a=0; //If the function is reversed, flip all the arguments if(!function.Upward) { flipped=true; for(int i=0;i<function.pArguments.Length;i++) { if(function.pArguments[i].Direction==VectorDirection.Up) { function.pArguments[i].Direction=VectorDirection.Down; } else if(function.pArguments[i].Direction==VectorDirection.Down) { function.pArguments[i].Direction=VectorDirection.Up; } } } while(function.calc.Length>1) { Operation op=DeepOp(ref function,a++); if(op.args==ArgsToUse.None) { op.op1loc=v3MoveToRegister(op.op1); op.args=ArgsToUse.Left; } if((op.args&ArgsToUse.Left)==0) { op.op1loc=v3MoveToRegister(op.op1); op.args|=ArgsToUse.Left; } if((op.args&ArgsToUse.Right)==0&&(!aligned||op.op2.Direction!=VectorDirection.Up)) { op.op2loc=v3MoveToRegister(op.op2); op.args|=ArgsToUse.Right; } Registers[op.op1loc].contains=(byte)(a-1); string s=null; switch(op.op) { case '+': s="addps "; break; case '-': s="subps "; break; case '*': s="mulps "; break; case '/': s="divps "; break; } if((op.args&ArgsToUse.Left)==0) { s+="["+op.op1.Register+ToHex(op.op1.Offset)+"],"; } else { s+="xmm"+op.op1loc+","; } if((op.args&ArgsToUse.Right)==0) { s+="["+op.op2.Register+ToHex(op.op2.Offset)+"]"; } else { s+="xmm"+op.op2loc; } AsmFile.WriteLine(s); } if(aligned) { AsmFile.WriteLine("movhlps xmm7,xmm"+GetRegister(function.calc[0])); if(flipped) { AsmFile.WriteLine("movlps ["+function.Reg+ToHex(function.Offset-4)+"],xmm"+GetRegister(function.calc[0])); AsmFile.WriteLine("movss ["+function.Reg+ToHex(function.Offset-8)+"],xmm7"); } else { AsmFile.WriteLine("movlps ["+function.Reg+ToHex(function.Offset)+"],xmm"+GetRegister(function.calc[0])); AsmFile.WriteLine("movss ["+function.Reg+ToHex(function.Offset+8)+"],xmm7"); } } else { if(flipped) { AsmFile.WriteLine("movhps ["+function.Reg+ToHex(function.Offset-8)+"],xmm"+GetRegister(function.calc[0])); } else { AsmFile.WriteLine("movhps ["+function.Reg+ToHex(function.Offset+4)+"],xmm"+GetRegister(function.calc[0])); } AsmFile.WriteLine("movss ["+function.Reg+ToHex(function.Offset)+"],xmm"+GetRegister(function.calc[0])); } }
public static void FindFpuLines(VectorMatch[] function) { ArrayList al=new ArrayList(); foreach(VectorMatch vm in function) { for(int i=0;i<vm.fpulines.Length;i++) { al.AddRange(vm.fpulines[i]); } } al.Sort(); //Remove duplicate references from fxch instructions int last=-1; for(int i=0;i<al.Count;i++) { if((int)al[i]==last) { al.RemoveAt(i--); } else { last=(int)al[i]; } } FpuLines=(int[])al.ToArray(typeof(int)); }
public static Operation DeepOp(ref VectorMatch vm, byte depth) { if (depth > 254) { throw new OptimizationException("Code generater: Too deep recursion"); } int count = 0; int maxcount = 0; int pos = 0; string s = vm.calc; for (int i = 0; i < s.Length; i++) { switch (s[i]) { case '(': count++; if (count > maxcount) { maxcount = count; } break; case ')': count--; break; } } for (int i = 0; i < s.Length; i++) { switch (s[i]) { case '(': count++; if (count == maxcount) { ArgsToUse atu = ArgsToUse.None; int b = 2; if (s[i + 1] != '$') { atu |= ArgsToUse.Left; b--; } if (s[i + 3] != '$') { atu |= ArgsToUse.Right; b--; } Operation o = new Operation(); switch (atu) { case ArgsToUse.None: o = new Operation(vm.pArguments[pos], vm.pArguments[pos + 1], s[i + 2]); break; case ArgsToUse.Left: o = new Operation(GetRegister(s[i + 1]), vm.pArguments[pos], s[i + 2]); //Registers[GetRegister(s[i+1])].contains=depth; break; case ArgsToUse.Right: o = new Operation(vm.pArguments[pos], GetRegister(s[i + 3]), s[i + 2]); break; case ArgsToUse.Both: o = new Operation(GetRegister(s[i + 3]), GetRegister(s[i + 1]), s[i + 2]); //Registers[GetRegister(s[i+1])].contains=depth; break; } Vector[] vs = new Vector[vm.pArguments.Length - b]; int c = 0; for (int a = 0; a < vm.pArguments.Length; a++) { if (a == c && b > 0) { continue; } if (a == c + 1 && b > 1) { continue; } vs[c++] = vm.pArguments[a]; } vm.pArguments = vs; vm.calc = s.Remove(i, 5); vm.calc = vm.calc.Insert(i, "" + (char)depth); return(o); } break; case ')': count--; break; case '$': pos++; break; } } throw new OptimizationException("Code generater: No operation to perform"); }
public static void v4CreateCode(VectorMatch function) { byte a = 0; while (function.calc.Length > 1) { Operation op = DeepOp(ref function, a++); if (op.args == ArgsToUse.None) { op.op1loc = v4MoveToRegister(op.op1); op.args = ArgsToUse.Left; } if ((op.args & ArgsToUse.Left) == 0) { op.op1loc = v4MoveToRegister(op.op1); op.args |= ArgsToUse.Left; } if ((op.args & ArgsToUse.Right) == 0 && (!aligned || op.op2.Direction != VectorDirection.Up)) { op.op2loc = v4MoveToRegister(op.op2); op.args |= ArgsToUse.Right; } Registers[op.op1loc].contains = (byte)(a - 1); string s = null; switch (op.op) { case '+': s = "addps "; break; case '-': s = "subps "; break; case '*': s = "mulps "; break; case '/': s = "divps "; break; } if ((op.args & ArgsToUse.Left) == 0) { s += "[" + op.op1.Register + ToHex(op.op1.Offset) + "],"; } else { s += "xmm" + op.op1loc + ","; } if ((op.args & ArgsToUse.Right) == 0) { s += "[" + op.op2.Register + ToHex(op.op2.Offset) + "]"; } else { s += "xmm" + op.op2loc; } AsmFile.WriteLine(s); } if (!function.Upward) { AsmFile.WriteLine("shufps xmm" + (byte)function.calc[0] + ",xmm" + GetRegister(function.calc[0]) + ",0x1B"); } if (aligned) { AsmFile.WriteLine("movaps [" + function.Reg + ToHex(function.Offset) + "],xmm" + GetRegister(function.calc[0])); } else { AsmFile.WriteLine("movups [" + function.Reg + ToHex(function.Offset) + "],xmm" + GetRegister(function.calc[0])); } }
public static void v3CreateCode(VectorMatch function) { byte a = 0; //If the function is reversed, flip all the arguments if (!function.Upward) { flipped = true; for (int i = 0; i < function.pArguments.Length; i++) { if (function.pArguments[i].Direction == VectorDirection.Up) { function.pArguments[i].Direction = VectorDirection.Down; } else if (function.pArguments[i].Direction == VectorDirection.Down) { function.pArguments[i].Direction = VectorDirection.Up; } } } while (function.calc.Length > 1) { Operation op = DeepOp(ref function, a++); if (op.args == ArgsToUse.None) { op.op1loc = v3MoveToRegister(op.op1); op.args = ArgsToUse.Left; } if ((op.args & ArgsToUse.Left) == 0) { op.op1loc = v3MoveToRegister(op.op1); op.args |= ArgsToUse.Left; } if ((op.args & ArgsToUse.Right) == 0 && (!aligned || op.op2.Direction != VectorDirection.Up)) { op.op2loc = v3MoveToRegister(op.op2); op.args |= ArgsToUse.Right; } Registers[op.op1loc].contains = (byte)(a - 1); string s = null; switch (op.op) { case '+': s = "addps "; break; case '-': s = "subps "; break; case '*': s = "mulps "; break; case '/': s = "divps "; break; } if ((op.args & ArgsToUse.Left) == 0) { s += "[" + op.op1.Register + ToHex(op.op1.Offset) + "],"; } else { s += "xmm" + op.op1loc + ","; } if ((op.args & ArgsToUse.Right) == 0) { s += "[" + op.op2.Register + ToHex(op.op2.Offset) + "]"; } else { s += "xmm" + op.op2loc; } AsmFile.WriteLine(s); } if (aligned) { AsmFile.WriteLine("movhlps xmm7,xmm" + GetRegister(function.calc[0])); if (flipped) { AsmFile.WriteLine("movlps [" + function.Reg + ToHex(function.Offset - 4) + "],xmm" + GetRegister(function.calc[0])); AsmFile.WriteLine("movss [" + function.Reg + ToHex(function.Offset - 8) + "],xmm7"); } else { AsmFile.WriteLine("movlps [" + function.Reg + ToHex(function.Offset) + "],xmm" + GetRegister(function.calc[0])); AsmFile.WriteLine("movss [" + function.Reg + ToHex(function.Offset + 8) + "],xmm7"); } } else { if (flipped) { AsmFile.WriteLine("movhps [" + function.Reg + ToHex(function.Offset - 8) + "],xmm" + GetRegister(function.calc[0])); } else { AsmFile.WriteLine("movhps [" + function.Reg + ToHex(function.Offset + 4) + "],xmm" + GetRegister(function.calc[0])); } AsmFile.WriteLine("movss [" + function.Reg + ToHex(function.Offset) + "],xmm" + GetRegister(function.calc[0])); } }
public static void GenerateCode(ArrayList function) { Reset(); AsmFile.WriteLine("bits 32"); for (int i = 0; i < function.Count; i++) { PartialReset(); VectorMatch vm = (VectorMatch)function[i]; int index = vm.Count - 2; if (Program.Mod[index]) { switch (Program.Align[index]) { case 3: aligned = true; break; case 2: if (vm.Offset % 16 == 0) { aligned = true; for (int j = 0; j < vm.pArguments.Length; j++) { if (vm.pArguments[j].Direction != VectorDirection.Static && vm.pArguments[j].Offset % 16 != 0) { aligned = false; } } } else { aligned = false; } break; case 1: if (vm.Offset == 0) { goto case 0; } for (int j = 0; j < Program.CurrentFpu.Pre.Length; j++) { if (Program.CurrentFpu.Pre[j].instruction == "push" || Program.CurrentFpu.Pre[j].instruction == "pop") { aligned = false; goto case 0; } } goto case 2; case 0: aligned = false; break; } switch (vm.Count) { case 2: v2CreateCode(vm); break; case 3: v3CreateCode(vm); break; case 4: v4CreateCode(vm); break; } } else { function.RemoveAt(i--); } } //Copy any leftover fpu lines to the asm file so the esp pointers get updated if (function.Count == 0) { throw new OptimizationException("Code generator: Unable to generate any code"); } FindFpuLines((VectorMatch[])function.ToArray(typeof(VectorMatch))); for (int i = 0; i < Program.CurrentFpu.Lines.Length; i++) { if (Array.IndexOf(FpuLines, i) == -1) { AsmFile.WriteLine(Program.CurrentFpu.Lines[i].instruction + " " + Program.CurrentFpu.Lines[i].StoredOperands); } } //Return AsmFile.Close(); }