1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "InterpKernelAsmX86.hxx"
26 #ifdef _POSIX_MAPPED_FILES
34 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"};
36 std::vector<char> INTERP_KERNEL::AsmX86::convertIntoMachineLangage(const std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
38 std::vector<char> ret;
39 for(std::vector<std::string>::const_iterator iter=asmb.begin();iter!=asmb.end();iter++)
40 convertOneInstructionInML(*iter,ret);
44 char *INTERP_KERNEL::AsmX86::copyToExecMemZone(const std::vector<char>& ml, unsigned& offset) const
48 #ifdef _POSIX_MAPPED_FILES
49 ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
52 HANDLE h=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,lgth,NULL);
53 ret=(char *)MapViewOfFile(h,FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE,0,0,lgth);
57 std::copy(ml.begin(),ml.end(),ret);
61 void INTERP_KERNEL::AsmX86::convertOneInstructionInML(const std::string& inst, std::vector<char>& ml) const throw(INTERP_KERNEL::Exception)
63 std::string::size_type pos=inst.find_first_of(' ');
66 if(pos!=std::string::npos)
68 op=inst.substr(0,pos);
69 param=inst.substr(pos+1);
74 for(const char **it=OPS;it!=OPS+NB_OF_OPS;it++,id++)
86 convertPush(param,ml);
95 convertFaddp(param,ml);
98 convertFsubp(param,ml);
101 convertFmulp(param,ml);
104 convertFdivp(param,ml);
107 convertFcos(param,ml);
110 convertFsin(param,ml);
113 convertFabs(param,ml);
116 convertFchs(param,ml);
119 convertFsqrt(param,ml);
122 convertSub(param,ml);
125 convertAdd(param,ml);
128 convertRet(param,ml);
131 convertLeave(param,ml);
134 convertMovsd(param,ml);
137 convertFst(param,ml);
141 std::ostringstream oss; oss << "Unrecognized op : " << op << " in assembly line : " << inst;
142 throw INTERP_KERNEL::Exception(oss.str().c_str());
149 void INTERP_KERNEL::AsmX86::convertMov(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
151 const char ASM1[]="ebp,esp";
152 const unsigned char ML1[2]={0x89,0xe5};
155 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
158 const char ASM2[]="rbp,rsp";
159 const unsigned char ML2[3]={0x48,0x89,0xe5};
162 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
165 std::string::size_type pos=inst.find_first_of(' ');
166 if(pos==std::string::npos)
168 std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
169 throw INTERP_KERNEL::Exception(oss.str().c_str());
171 std::string inst2=inst.substr(pos+1);
172 pos=inst2.find_first_of(',');
173 if(pos==std::string::npos)
175 std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
176 throw INTERP_KERNEL::Exception(oss.str().c_str());
178 std::string inst3=inst2.substr(0,pos);
179 std::string inst4=inst2.substr(pos+1);
180 convertMovToEsp(inst3,inst4,ml);
183 void INTERP_KERNEL::AsmX86::convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
185 if(inst1[0]!='[' || inst1[inst1.length()-1]!=']')
186 throw INTERP_KERNEL::Exception("not recognized convertMovToEsp exp !");
187 std::string inst1bis=inst1.substr(1,inst1.length()-2);
188 const char ASM1[]="esp";
189 const unsigned char ML1[3]={0xc7,0x04,0x24};
191 {//mov dword [esp],0x3ff3c0ca
192 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
193 appendAddress(inst2,4,ml);
196 if(inst1bis.substr(0,3)==ASM1)
199 {//mov dword [esp+4],0x3ff3c0ca
200 const unsigned char ML2[3]={0xc7,0x44,0x24};
201 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
202 std::string::size_type pos=inst1bis.find_first_of(']');
203 std::string inst1_1=inst1bis.substr(4,pos-4-1);
204 appendAddress(inst1_1,1,ml);
205 appendAddress(inst2,4,ml);
209 throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
211 const char ASM3[]="rsp";
212 const unsigned char ML3[3]={0xc7,0x04,0x24};
214 {//mov dword [rsp],0x3ff3c0ca
215 ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
216 appendAddress(inst2,4,ml);
219 if(inst1bis.substr(0,3)==ASM3)
222 {//mov dword [rsp+4],0x3ff3c0ca
223 const unsigned char ML2[3]={0xc7,0x44,0x24};
224 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
225 std::string::size_type pos=inst1bis.find_first_of(']');
226 std::string inst1_1=inst1bis.substr(4,pos-4-1);
227 appendAddress(inst1_1,1,ml);
228 appendAddress(inst2,4,ml);
232 throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
234 throw INTERP_KERNEL::Exception("Not recognized exp : mov");
237 void INTERP_KERNEL::AsmX86::convertPush(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
239 std::string::size_type pos=inst.find_first_of(' ');
240 std::string inst2=inst.substr(pos+1);
241 const char ASM1[]="ebp";
242 const unsigned char ML1[1]={0x55};
245 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
248 const char ASM2[]="ebx";
249 const unsigned char ML2[1]={0x53};
252 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
255 const char ASM3[]="rbp";
256 const unsigned char ML3[1]={0x55};
259 ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
262 throw INTERP_KERNEL::Exception("Unrecognized push instruction");
265 void INTERP_KERNEL::AsmX86::convertPop(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
267 std::string::size_type pos=inst.find_first_of(' ');
268 std::string inst2=inst.substr(pos+1);
269 const char ASM1[]="ebp";
270 const unsigned char ML1[1]={0x5d};
273 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
276 const char ASM2[]="ebx";
277 const unsigned char ML2[1]={0x5b};
280 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
283 throw INTERP_KERNEL::Exception("Unrecognized pop instruction");
286 void INTERP_KERNEL::AsmX86::convertFld(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
288 std::string::size_type pos=inst.find_first_of(' ');
289 std::string params=inst.substr(pos+1);
290 std::string params2=params.substr(1,params.length()-2);
291 if(params2.substr(0,3)=="esp")
293 const unsigned char ML1[3]={0xdd,0x04,0x24};
294 if(params2.length()==3)
296 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
299 pos=params2.find_first_of('+');
300 if(pos!=std::string::npos)
302 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
303 std::string params3=params2.substr(pos+1);
304 appendAddress(params3,1,ml);
307 throw INTERP_KERNEL::Exception("Unrecognized fld esp...");
309 if(params2.substr(0,3)=="ebp")
311 const unsigned char ML2[2]={0xdd,0x45};
312 if(params2.length()==3)
314 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
318 pos=params2.find_first_of('+');
319 if(pos!=std::string::npos)
321 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
322 std::string params3=params2.substr(pos+1);
323 appendAddress(params3,1,ml);
326 throw INTERP_KERNEL::Exception("Unrecognized fld ebp...");
328 if(params2.substr(0,3)=="rsp")
330 const unsigned char ML2[3]={0xdd,0x04,0x24};
331 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));// to improve ! no fully managed !
334 throw INTERP_KERNEL::Exception("Unrecognized fld instruction");
337 void INTERP_KERNEL::AsmX86::convertFaddp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
339 const unsigned char ML1[2]={0xde,0xc1};
340 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
343 void INTERP_KERNEL::AsmX86::convertFsubp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
345 const unsigned char ML1[2]={0xde,0xe9};
346 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
349 void INTERP_KERNEL::AsmX86::convertFmulp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
351 const unsigned char ML1[2]={0xde,0xc9};
352 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
355 void INTERP_KERNEL::AsmX86::convertFdivp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
357 const unsigned char ML1[2]={0xde,0xf9};
358 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
361 void INTERP_KERNEL::AsmX86::convertFcos(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
363 const unsigned char ML[2]={0xd9,0xff};
364 ml.insert(ml.end(),ML,ML+sizeof(ML));
367 void INTERP_KERNEL::AsmX86::convertFsin(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
369 const unsigned char ML[2]={0xd9,0xfe};
370 ml.insert(ml.end(),ML,ML+sizeof(ML));
373 void INTERP_KERNEL::AsmX86::convertFabs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
375 const unsigned char ML[2]={0xd9,0xe1};
376 ml.insert(ml.end(),ML,ML+sizeof(ML));
379 void INTERP_KERNEL::AsmX86::convertFchs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
381 const unsigned char ML[2]={0xd9,0xe0};
382 ml.insert(ml.end(),ML,ML+sizeof(ML));
385 void INTERP_KERNEL::AsmX86::convertFsqrt(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
387 const unsigned char ML[2]={0xd9,0xfa};
388 ml.insert(ml.end(),ML,ML+sizeof(ML));
391 void INTERP_KERNEL::AsmX86::convertSub(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
393 if(inst.substr(0,4)=="esp,")
395 const unsigned char ML[2]={0x81,0xec};
396 ml.insert(ml.end(),ML,ML+sizeof(ML));
397 std::string inst2=inst.substr(4);
398 appendAddress(inst2,4,ml);
401 if(inst.substr(0,4)=="rsp,")
403 const unsigned char ML[4]={0x48,0x83,0xec,0x08};
404 ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
407 throw INTERP_KERNEL::Exception("Not recognized sub instruction.");
410 void INTERP_KERNEL::AsmX86::convertAdd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
412 if(inst.substr(0,4)=="esp,")
414 const unsigned char ML[2]={0x81,0xc4};
415 ml.insert(ml.end(),ML,ML+sizeof(ML));
416 std::string inst2=inst.substr(4);
417 appendAddress(inst2,4,ml);
420 if(inst.substr(0,4)=="rsp,")
422 const unsigned char ML[4]={0x48,0x83,0xc4,0x08};
423 ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
426 throw INTERP_KERNEL::Exception("Not recognized add instruction.");
429 void INTERP_KERNEL::AsmX86::convertRet(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
431 const unsigned char ML[1]={0xc3};
432 ml.insert(ml.end(),ML,ML+sizeof(ML));
435 void INTERP_KERNEL::AsmX86::convertLeave(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
437 const unsigned char ML[1]={0xc9};
438 ml.insert(ml.end(),ML,ML+sizeof(ML));
441 void INTERP_KERNEL::AsmX86::convertMovsd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
443 const char ASM1[]="[rsp],xmm0";
444 const unsigned char ML1[5]={0xf2,0x0f,0x11,0x04,0x24};
447 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
450 const char ASM2[]="xmm0,[rsp]";
451 const unsigned char ML2[5]={0xf2,0x0f,0x10,0x04,0x24};
454 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
457 std::ostringstream oss; oss << "not recognized instruction movsd : " << inst;
458 throw INTERP_KERNEL::Exception(oss.str().c_str());
461 void INTERP_KERNEL::AsmX86::convertFst(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
463 const char ASM1[]="qword [rsp]";
464 const unsigned char ML1[3]={0xdd,0x14,0x24};
467 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
470 std::ostringstream oss; oss << "not recognized instruction fst : " << inst;
471 throw INTERP_KERNEL::Exception(oss.str().c_str());
476 void INTERP_KERNEL::AsmX86::appendAddress(const std::string& addr, int nbOfByte, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
480 std::istringstream iss(addr);
483 if(addr[0]=='0' && addr[1]=='x')
487 for(int k=0;k<nbOfByte;k++)