/// <summary> /// This is too add an fpu line to a new fpu segment - all lines in here are fpu commands /// </summary> public void AddLine(LineInfo li,int LinoNo) { //Check for illegal opperand data if(li.StoredOperands.IndexOf(",")!=-1) { //TODO: Make this a bit more general if(li.instruction=="fdivp"&&li.operands[0].Register=="st1"&&li.operands[1].Register=="st0") { li=new LineInfo(li.address+" "+li.code+" fdivrp st1"); } else { throw new OptimizationException("Segmenter: Fpu instruction had 2 operands"); } } if(li.StoredOperands=="") throw new OptimizationException("Segmenter: Fpu instruction had no operands"); //TODO: Check that this line of code doesn't break anything! if(Array.IndexOf(Program.FpuIgnoreInstructions,li.instruction)!=-1||li.operands[0].OpType== OperandType.Register) return; if(li.operands[0].OpType!=OperandType.rMemory) throw new OptimizationException("Segmenter: Cannot do anything with non memory operands"); if(li.operands[0].MultiPart) throw new OptimizationException("Segmenter: Cannot do anything with multipart operands"); if(li.operands[0].OpSize!=OperandSize.Unknown&&li.operands[0].OpSize!=OperandSize.dWord) throw new OptimizationException("Segmenter: Cannot do anything with non float data values"); if(Math.Abs(li.operands[0].Offset)>65535) throw new OptimizationException("Segmenter: Memory offset is too great"); //Add the operand to the appropriate arraylists if(Array.IndexOf(Program.FpuReadInstructions,li.instruction)!=-1) { ReadMem.Add(new IntString(LinoNo,li.operands[0].Operand)); if(!ScanList(ChangedMem,LinoNo,li.operands[0].Operand,true)) throw new OptimizationException("Segmenter: Interdependent fpu calculations"); } if(Array.IndexOf(Program.FpuWriteInstructions,li.instruction)!=-1) { ChangedMem.Add(new IntString(LinoNo,li.operands[0].Operand)); } ReadReg.Add(new IntString(LinoNo,li.operands[0].Register)); }
//public string[] TestData; public FpuSegment(LineInfo[] lines,ArrayList pre,ArrayList post,int start,int end) { Lines=lines; Pre=(LineInfo[])pre.ToArray(typeof(LineInfo)); Post=(LineInfo[])post.ToArray(typeof(LineInfo)); Start=start; End=end; //TestData=(string[])testData.ToArray(typeof(string)); }
public bool CanMoveInstruction(LineInfo li,int LineNo,bool upward) { if(li.operands.Length>2) throw new OptimizationException("Segmenter: Cannot move instructions with 3 operands"); if(li.operands.Length==0) throw new OptimizationException("Segmenter: Cannot move instructions with implicit operands"); if(li.operands.Length==1) { switch(li.instruction) { case "push": switch(li.operands[0].OpType) { case OperandType.rMemory: if(!ScanList(ChangedMem,LineNo,li.operands[0].Operand,upward)) return false; break; case OperandType.Immediate: throw new OptimizationException("Segmenter: Immediate operand pushed onto stack"); } if(upward) { ModEsp(LineNo,upward,4); } else { ModEsp(LineNo,upward,-4); } break; //li=new LineInfo("00000000 00 mov esp,"+li.operands[0].Operand);break; case "pop": switch(li.operands[0].OpType) { case OperandType.rMemory: if(!ScanList(ReadMem,LineNo,li.operands[0].Operand,upward)) return false; break; case OperandType.Register: if(!ScanList(ReadReg,LineNo,li.operands[0].Operand,upward)) return false; break; } if(upward) { ModEsp(LineNo,upward,-4); } else { ModEsp(LineNo,upward,4); } break; //li=new LineInfo("00000000 00 mov esp,[esp]"); break; default: throw new OptimizationException("Segmenter: Cannot move instruction with one operand"); } } if(li.operands.Length==2) { if(Array.IndexOf(Program.ReadOnlyInstructions,li.instruction)==-1) { switch(li.operands[0].OpType) { case OperandType.Register: if(!ScanList(ReadReg,LineNo,li.operands[0].Register,upward)) return false; break; case OperandType.rMemory: if(!ScanList(ReadMem,LineNo,li.operands[0].Operand,upward)) return false; break; } } else { switch(li.operands[0].OpType) { case OperandType.rMemory: if(!ScanList(ChangedMem,LineNo,li.operands[1].Operand,upward)) return false; break; } } switch(li.operands[1].OpType) { case OperandType.rMemory: if(!ScanList(ChangedMem,LineNo,li.operands[1].Operand,upward)) return false; break; } } return true; }
public static void ReadCode() { #if clean File.Delete("Morrowind.exe"); File.Delete("code"); File.Copy("clean\\Morrowind.exe","Morrowind.exe"); File.Copy("clean\\code","code"); #endif Console.WriteLine("Loading code segments"); StreamReader sr=new StreamReader("dcode.txt"); ArrayList segLines=new ArrayList(); int count=0; bool DropSegment=false; bool StartedSegment=true; LineInfo li; #if !fulltest||partialtest int count2=0; #endif count3=0; while(sr.Peek()!=-1) { string s=sr.ReadLine(); #if !fulltest||partialtest count2++; LineNo=count2; if(count2<500000||count2>510000) continue; #endif try { li=new LineInfo(s); } catch(Exception) { DropSegment=true; li=new LineInfo("00000000 00 int3"); } if(Array.IndexOf(JumpInstructions,li.instruction)==-1) { if(StartedSegment) { segLines.Add(li); } else if(Array.IndexOf(FpuInstructions,li.instruction)!=-1) { StartedSegment=true; segLines.Add(li); } } else if(StartedSegment) { if(!DropSegment) { segLines.Add(li); CodeSegment cs=new CodeSegment(segLines); try { if(OptimizeSegment(ref cs)) count3++; #if !fulltest } catch(OptimizationException ex) { if(thingy) { try { LogFile.WriteLine(CurrentSeg.Lines[0].address); LogFile.WriteLine("\nPatched:"); LogFile.Write(CurrentSeg.ToString()); LogFile.WriteLine("\nwith:"); s=string.Join("\n",fpu.Result); LogFile.WriteLine(s); //LogFile.Write(tempFpu.PreString()+File.ReadAll("out.txt")+tempFpu.PostString()); LogFile.WriteLine("------------------------------------------------"); } catch { } string ss=ex.ToString(); Console.WriteLine(ss); thingy=false; } #else } catch(OptimizationException) { #endif } count++; #if useconsole if(count%100==0) { Console.WriteLine("Processed "+count.ToString()+" segments and found "+count3+" patches."); } #else Console.WriteLine("Processed "+count.ToString()+" segments and found "+count3+" patches."); #endif } segLines.Clear(); DropSegment=false; StartedSegment=false; } else DropSegment=false; } sr.Close(); }
public static void PerformOp(LineInfo op,byte LineNo) { string l="\0"+LineNo.ToString().PadLeft(10,'0'); CurrentOp=op; switch(op.instruction) { case "fld": Registers.Push(loc(),l); break; case "fst": if(CurrentOp.operands[0].OpType==OperandType.Register) { byte b=Convert.ToByte(""+CurrentOp.operands[0].Register[2]); Registers.Assign(b,Registers.Peek(),l); } else { Results.Add(l+loc()+"="+Registers.Peek()); } break; case "fstp": //This is backwards! Assign first, then pop! if(CurrentOp.operands[0].OpType==OperandType.Register) { byte b=Convert.ToByte(""+CurrentOp.operands[0].Register[2]); Registers.Assign(b,Registers.Peek(),l); Registers.Pop(); } else { Results.Add(l+loc()+"="+Registers.Pop()); } break; case "fadd": Registers.Op(l+"+",loc()); break; case "faddp": Registers.ToOp(l+"+",loc()); Registers.Pop(); break; case "fmul": Registers.Op(l+"*",loc()); break; case "fmulp": Registers.ToOp(l+"*",loc()); Registers.Pop(); break; case "fdiv": Registers.Op(l+"/",loc()); break; case "fdivp": Registers.ToOp(l+"/",loc()); Registers.Pop(); break; case "fdivr": Registers.ROp(l+"/",loc()); break; case "fdivrp": Registers.RToOp(l+"/",loc()); Registers.Pop(); break; case "fsub": Registers.Op(l+"-",loc()); break; case "fsubp": Registers.ToOp(l+"-",loc()); Registers.Pop(); break; case "fsubr": Registers.ROp(l+"-",loc()); break; case "fsubrp": Registers.RToOp(l+"-",loc()); Registers.Pop(); break; case "fxch": Registers.Exchange(loc(),l); break; default: throw new OptimizationException("FPU: Unrecognised operation"); } }
public bool CanMoveInstruction(LineInfo li, int LineNo, bool upward) { if (li.operands.Length > 2) { throw new OptimizationException("Segmenter: Cannot move instructions with 3 operands"); } if (li.operands.Length == 0) { throw new OptimizationException("Segmenter: Cannot move instructions with implicit operands"); } if (li.operands.Length == 1) { switch (li.instruction) { case "push": switch (li.operands[0].OpType) { case OperandType.rMemory: if (!ScanList(ChangedMem, LineNo, li.operands[0].Operand, upward)) { return(false); } break; case OperandType.Immediate: throw new OptimizationException("Segmenter: Immediate operand pushed onto stack"); } if (upward) { ModEsp(LineNo, upward, 4); } else { ModEsp(LineNo, upward, -4); } break; //li=new LineInfo("00000000 00 mov esp,"+li.operands[0].Operand);break; case "pop": switch (li.operands[0].OpType) { case OperandType.rMemory: if (!ScanList(ReadMem, LineNo, li.operands[0].Operand, upward)) { return(false); } break; case OperandType.Register: if (!ScanList(ReadReg, LineNo, li.operands[0].Operand, upward)) { return(false); } break; } if (upward) { ModEsp(LineNo, upward, -4); } else { ModEsp(LineNo, upward, 4); } break; //li=new LineInfo("00000000 00 mov esp,[esp]"); break; default: throw new OptimizationException("Segmenter: Cannot move instruction with one operand"); } } if (li.operands.Length == 2) { if (Array.IndexOf(Program.ReadOnlyInstructions, li.instruction) == -1) { switch (li.operands[0].OpType) { case OperandType.Register: if (!ScanList(ReadReg, LineNo, li.operands[0].Register, upward)) { return(false); } break; case OperandType.rMemory: if (!ScanList(ReadMem, LineNo, li.operands[0].Operand, upward)) { return(false); } break; } } else { switch (li.operands[0].OpType) { case OperandType.rMemory: if (!ScanList(ChangedMem, LineNo, li.operands[1].Operand, upward)) { return(false); } break; } } switch (li.operands[1].OpType) { case OperandType.rMemory: if (!ScanList(ChangedMem, LineNo, li.operands[1].Operand, upward)) { return(false); } break; } } return(true); }