Back to index

salome-med  6.5.0
InterpKernelAsmX86.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "InterpKernelAsmX86.hxx"
00021 
00022 #include <cstring>
00023 #include <sstream>
00024 #include <algorithm>
00025 
00026 #ifdef _POSIX_MAPPED_FILES
00027 #include <sys/mman.h>
00028 #else
00029 #ifdef WNT
00030 #include <windows.h>
00031 #endif
00032 #endif
00033 
00034 const char *INTERP_KERNEL::AsmX86::OPS[NB_OF_OPS]={"mov","push","pop","fld","faddp","fsubp","fmulp","fdivp","fcos","fsin","fabs","fchs","fsqrt","sub","add","ret","leave","movsd","fst"};
00035 
00036 std::vector<char> INTERP_KERNEL::AsmX86::convertIntoMachineLangage(const std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
00037 {
00038   std::vector<char> ret;
00039   for(std::vector<std::string>::const_iterator iter=asmb.begin();iter!=asmb.end();iter++)
00040     convertOneInstructionInML(*iter,ret);
00041   return ret;
00042 }
00043 
00044 char *INTERP_KERNEL::AsmX86::copyToExecMemZone(const std::vector<char>& ml, unsigned& offset) const
00045 {
00046   char *ret=0;
00047   int lgth=ml.size();
00048 #ifdef _POSIX_MAPPED_FILES
00049   ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
00050 #else
00051 #ifdef WNT
00052   HANDLE h=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,lgth,NULL);
00053   ret=(char *)MapViewOfFile(h,FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE,0,0,lgth);
00054 #endif
00055 #endif
00056   if(ret)
00057     std::copy(ml.begin(),ml.end(),ret);
00058   return ret;
00059 }
00060 
00061 void INTERP_KERNEL::AsmX86::convertOneInstructionInML(const std::string& inst, std::vector<char>& ml) const throw(INTERP_KERNEL::Exception)
00062 {
00063   std::string::size_type pos=inst.find_first_of(' ');
00064   std::string op;
00065   std::string param;
00066   if(pos!=std::string::npos)
00067     {
00068       op=inst.substr(0,pos);
00069       param=inst.substr(pos+1);
00070     }
00071   else
00072     op=inst;
00073   int id=0;
00074   for(const char **it=OPS;it!=OPS+NB_OF_OPS;it++,id++)
00075     {
00076       std::string tmp(*it);
00077       if(op==tmp)
00078         break;
00079     }
00080   switch(id)
00081     {
00082     case 0:
00083       convertMov(param,ml);
00084       break;
00085     case 1:
00086       convertPush(param,ml);
00087       break;
00088     case 2:
00089       convertPop(param,ml);
00090       break;
00091     case 3:
00092       convertFld(param,ml);
00093       break;
00094     case 4:
00095       convertFaddp(param,ml);
00096       break;
00097     case 5:
00098       convertFsubp(param,ml);
00099       break;
00100     case 6:
00101       convertFmulp(param,ml);
00102       break;
00103     case 7:
00104       convertFdivp(param,ml);
00105       break;
00106     case 8:
00107       convertFcos(param,ml);
00108       break;
00109     case 9:
00110       convertFsin(param,ml);
00111       break;
00112     case 10:
00113       convertFabs(param,ml);
00114       break;
00115     case 11:
00116       convertFchs(param,ml);
00117       break;
00118     case 12:
00119       convertFsqrt(param,ml);
00120       break;
00121     case 13:
00122       convertSub(param,ml);
00123       break;
00124     case 14:
00125       convertAdd(param,ml);
00126       break;
00127     case 15:
00128       convertRet(param,ml);
00129       break;
00130     case 16:
00131       convertLeave(param,ml);
00132       break;
00133     case 17:
00134       convertMovsd(param,ml);
00135       break;
00136     case 18:
00137       convertFst(param,ml);
00138       break;
00139     default:
00140       {
00141         std::ostringstream oss; oss << "Unrecognized op : " << op << " in assembly line : " << inst;
00142         throw INTERP_KERNEL::Exception(oss.str().c_str());
00143       }
00144     }
00145 }
00146 
00147 #include <iostream>
00148 
00149 void INTERP_KERNEL::AsmX86::convertMov(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00150 {
00151   const char ASM1[]="ebp,esp";
00152   const unsigned char ML1[2]={0x89,0xe5};
00153   if(inst==ASM1)
00154     {
00155       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00156       return ;
00157     }
00158   const char ASM2[]="rbp,rsp";
00159   const unsigned char ML2[3]={0x48,0x89,0xe5};
00160   if(inst==ASM2)
00161     {
00162       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00163       return ;
00164     }
00165   std::string::size_type pos=inst.find_first_of(' ');
00166   if(pos==std::string::npos)
00167     {
00168       std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
00169       throw INTERP_KERNEL::Exception(oss.str().c_str());
00170     }
00171   std::string inst2=inst.substr(pos+1);
00172   pos=inst2.find_first_of(',');
00173   if(pos==std::string::npos)
00174     {
00175       std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
00176       throw INTERP_KERNEL::Exception(oss.str().c_str());
00177     }
00178   std::string inst3=inst2.substr(0,pos);
00179   std::string inst4=inst2.substr(pos+1);
00180   convertMovToEsp(inst3,inst4,ml);
00181 }
00182 
00183 void INTERP_KERNEL::AsmX86::convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00184 {
00185   if(inst1[0]!='[' || inst1[inst1.length()-1]!=']')
00186     throw INTERP_KERNEL::Exception("not recognized convertMovToEsp exp !");
00187   std::string inst1bis=inst1.substr(1,inst1.length()-2);
00188   const char ASM1[]="esp";
00189   const unsigned char ML1[3]={0xc7,0x04,0x24};
00190   if(inst1bis==ASM1)
00191     {//mov dword [esp],0x3ff3c0ca
00192       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00193       appendAddress(inst2,4,ml);
00194       return ;
00195     }
00196   if(inst1bis.substr(0,3)==ASM1)
00197     {
00198       if(inst1bis[3]=='+')
00199         {//mov dword [esp+4],0x3ff3c0ca
00200           const unsigned char ML2[3]={0xc7,0x44,0x24};
00201           ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00202           std::string::size_type pos=inst1bis.find_first_of(']');
00203           std::string inst1_1=inst1bis.substr(4,pos-4-1);
00204           appendAddress(inst1_1,1,ml);
00205           appendAddress(inst2,4,ml);
00206           return;
00207         }
00208       else
00209         throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
00210     }
00211   const char ASM3[]="rsp";
00212   const unsigned char ML3[3]={0xc7,0x04,0x24};
00213   if(inst1bis==ASM3)
00214     {//mov dword [rsp],0x3ff3c0ca
00215       ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
00216       appendAddress(inst2,4,ml);
00217       return ;
00218     }
00219   if(inst1bis.substr(0,3)==ASM3)
00220     {
00221       if(inst1bis[3]=='+')
00222         {//mov dword [rsp+4],0x3ff3c0ca
00223           const unsigned char ML2[3]={0xc7,0x44,0x24};
00224           ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00225           std::string::size_type pos=inst1bis.find_first_of(']');
00226           std::string inst1_1=inst1bis.substr(4,pos-4-1);
00227           appendAddress(inst1_1,1,ml);
00228           appendAddress(inst2,4,ml);
00229           return;
00230         }
00231       else
00232         throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
00233     }
00234   throw INTERP_KERNEL::Exception("Not recognized exp : mov");
00235 }
00236 
00237 void INTERP_KERNEL::AsmX86::convertPush(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00238 {
00239   std::string::size_type pos=inst.find_first_of(' ');
00240   std::string inst2=inst.substr(pos+1);
00241   const char ASM1[]="ebp";
00242   const unsigned char ML1[1]={0x55};
00243   if(inst2==ASM1)
00244     {//push ebp
00245       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00246       return ;
00247     }
00248   const char ASM2[]="ebx";
00249   const unsigned char ML2[1]={0x53};
00250   if(inst2==ASM2)
00251     {//push ebx
00252       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00253       return ;
00254     }
00255   const char ASM3[]="rbp";
00256   const unsigned char ML3[1]={0x55};
00257   if(inst2==ASM3)
00258     {//push rbp
00259       ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
00260       return ;
00261     }
00262   throw INTERP_KERNEL::Exception("Unrecognized push instruction");
00263 }
00264 
00265 void INTERP_KERNEL::AsmX86::convertPop(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00266 {
00267   std::string::size_type pos=inst.find_first_of(' ');
00268   std::string inst2=inst.substr(pos+1);
00269   const char ASM1[]="ebp";
00270   const unsigned char ML1[1]={0x5d};
00271   if(inst2==ASM1)
00272     {//push ebp
00273       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00274       return ;
00275     }
00276   const char ASM2[]="ebx";
00277   const unsigned char ML2[1]={0x5b};
00278   if(inst2==ASM2)
00279     {//push ebx
00280       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00281       return ;
00282     }
00283   throw INTERP_KERNEL::Exception("Unrecognized pop instruction");
00284 }
00285 
00286 void INTERP_KERNEL::AsmX86::convertFld(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00287 {
00288   std::string::size_type pos=inst.find_first_of(' ');
00289   std::string params=inst.substr(pos+1);
00290   std::string params2=params.substr(1,params.length()-2);
00291   if(params2.substr(0,3)=="esp")
00292     {
00293       const unsigned char ML1[3]={0xdd,0x04,0x24};
00294       if(params2.length()==3)
00295         {//fld qword [esp]
00296           ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00297           return ;
00298         }
00299       pos=params2.find_first_of('+');
00300       if(pos!=std::string::npos)
00301         {//fld qword [esp+@]
00302           ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00303           std::string params3=params2.substr(pos+1);
00304           appendAddress(params3,1,ml);
00305           return ;
00306         }
00307       throw INTERP_KERNEL::Exception("Unrecognized fld esp...");
00308     }
00309   if(params2.substr(0,3)=="ebp")
00310     {
00311       const unsigned char ML2[2]={0xdd,0x45};
00312       if(params2.length()==3)
00313         {//fld qword [ebp]
00314           ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00315           ml.push_back(0);
00316           return ;
00317         }
00318       pos=params2.find_first_of('+');
00319       if(pos!=std::string::npos)
00320         {//fld qword [esp+@]
00321           ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00322           std::string params3=params2.substr(pos+1);
00323           appendAddress(params3,1,ml);
00324           return ;
00325         }
00326       throw INTERP_KERNEL::Exception("Unrecognized fld ebp...");
00327     }
00328   if(params2.substr(0,3)=="rsp")
00329     {
00330       const unsigned char ML2[3]={0xdd,0x04,0x24};
00331       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));// to improve ! no fully managed !
00332       return ;
00333     }
00334   throw INTERP_KERNEL::Exception("Unrecognized fld instruction");
00335 }
00336 
00337 void INTERP_KERNEL::AsmX86::convertFaddp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00338 {
00339   const unsigned char ML1[2]={0xde,0xc1};
00340   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00341 }
00342 
00343 void INTERP_KERNEL::AsmX86::convertFsubp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00344 {
00345   const unsigned char ML1[2]={0xde,0xe9};
00346   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00347 }
00348 
00349 void INTERP_KERNEL::AsmX86::convertFmulp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00350 {
00351   const unsigned char ML1[2]={0xde,0xc9};
00352   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00353 }
00354 
00355 void INTERP_KERNEL::AsmX86::convertFdivp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00356 {
00357   const unsigned char ML1[2]={0xde,0xf9};
00358   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00359 }
00360 
00361 void INTERP_KERNEL::AsmX86::convertFcos(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00362 {
00363   const unsigned char ML[2]={0xd9,0xff};
00364   ml.insert(ml.end(),ML,ML+sizeof(ML));
00365 }
00366 
00367 void INTERP_KERNEL::AsmX86::convertFsin(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00368 {
00369   const unsigned char ML[2]={0xd9,0xfe};
00370   ml.insert(ml.end(),ML,ML+sizeof(ML));
00371 }
00372 
00373 void INTERP_KERNEL::AsmX86::convertFabs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00374 {
00375   const unsigned char ML[2]={0xd9,0xe1};
00376   ml.insert(ml.end(),ML,ML+sizeof(ML));
00377 }
00378 
00379 void INTERP_KERNEL::AsmX86::convertFchs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00380 {
00381   const unsigned char ML[2]={0xd9,0xe0};
00382   ml.insert(ml.end(),ML,ML+sizeof(ML));
00383 }
00384 
00385 void INTERP_KERNEL::AsmX86::convertFsqrt(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00386 {
00387   const unsigned char ML[2]={0xd9,0xfa};
00388   ml.insert(ml.end(),ML,ML+sizeof(ML));
00389 }
00390 
00391 void INTERP_KERNEL::AsmX86::convertSub(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00392 {
00393   if(inst.substr(0,4)=="esp,")
00394     {
00395       const unsigned char ML[2]={0x81,0xec};
00396       ml.insert(ml.end(),ML,ML+sizeof(ML));
00397       std::string inst2=inst.substr(4);
00398       appendAddress(inst2,4,ml);
00399       return;
00400     }
00401   if(inst.substr(0,4)=="rsp,")
00402     {
00403       const unsigned char ML[4]={0x48,0x83,0xec,0x08};
00404       ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
00405       return;
00406     }
00407   throw INTERP_KERNEL::Exception("Not recognized sub instruction.");
00408 }
00409 
00410 void INTERP_KERNEL::AsmX86::convertAdd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00411 {
00412   if(inst.substr(0,4)=="esp,")
00413     {
00414       const unsigned char ML[2]={0x81,0xc4};
00415       ml.insert(ml.end(),ML,ML+sizeof(ML));
00416       std::string inst2=inst.substr(4);
00417       appendAddress(inst2,4,ml);
00418       return;
00419     }
00420   if(inst.substr(0,4)=="rsp,")
00421     {
00422       const unsigned char ML[4]={0x48,0x83,0xc4,0x08};
00423       ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
00424       return;
00425     }
00426   throw INTERP_KERNEL::Exception("Not recognized add instruction.");
00427 }
00428 
00429 void INTERP_KERNEL::AsmX86::convertRet(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00430 {
00431   const unsigned char ML[1]={0xc3};
00432   ml.insert(ml.end(),ML,ML+sizeof(ML));
00433 }
00434 
00435 void INTERP_KERNEL::AsmX86::convertLeave(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00436 {
00437   const unsigned char ML[1]={0xc9};
00438   ml.insert(ml.end(),ML,ML+sizeof(ML));
00439 }
00440 
00441 void INTERP_KERNEL::AsmX86::convertMovsd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00442 {
00443   const char ASM1[]="[rsp],xmm0";
00444   const unsigned char ML1[5]={0xf2,0x0f,0x11,0x04,0x24};
00445   if(inst==ASM1)
00446     {
00447       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00448       return ;
00449     }
00450   const char ASM2[]="xmm0,[rsp]";
00451   const unsigned char ML2[5]={0xf2,0x0f,0x10,0x04,0x24};
00452   if(inst==ASM2)
00453     {
00454       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
00455       return ;
00456     }
00457   std::ostringstream oss; oss << "not recognized instruction movsd : " << inst;
00458   throw INTERP_KERNEL::Exception(oss.str().c_str());
00459 }
00460 
00461 void INTERP_KERNEL::AsmX86::convertFst(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00462 {
00463   const char ASM1[]="qword [rsp]";
00464   const unsigned char ML1[3]={0xdd,0x14,0x24};
00465   if(inst==ASM1)
00466     {
00467       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
00468       return ;
00469     }
00470   std::ostringstream oss; oss << "not recognized instruction fst : " << inst;
00471   throw INTERP_KERNEL::Exception(oss.str().c_str());
00472   //tony
00473 }
00474 
00475 
00476 void INTERP_KERNEL::AsmX86::appendAddress(const std::string& addr, int nbOfByte, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
00477 {
00478   int i,j;
00479   char v;
00480   std::istringstream iss(addr);
00481   if(addr.length()>2)
00482     {
00483       if(addr[0]=='0' && addr[1]=='x')
00484         iss >> std::hex;
00485     }
00486   iss >> i;
00487   for(int k=0;k<nbOfByte;k++)
00488     {
00489       j=i&255;
00490       v=j;
00491       ml.push_back(v);
00492       i>>=8;
00493     }
00494 }