1 // Copyright (C) 2007-2024 CEA, EDF
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, or (at your option) any later version.
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
19 // Author : Anthony Geay (CEA/DEN)
21 #include "InterpKernelAsmX86.hxx"
27 #ifdef _POSIX_MAPPED_FILES
35 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"};
37 std::vector<char> INTERP_KERNEL::AsmX86::convertIntoMachineLangage(const std::vector<std::string>& asmb) const
39 std::vector<char> ret;
40 for(std::vector<std::string>::const_iterator iter=asmb.begin();iter!=asmb.end();iter++)
41 convertOneInstructionInML(*iter,ret);
45 char *INTERP_KERNEL::AsmX86::copyToExecMemZone(const std::vector<char>& ml, unsigned& offset) const
48 std::size_t lgth=ml.size();
49 #ifdef _POSIX_MAPPED_FILES
51 ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANON | MAP_PRIVATE,-1,0);
53 ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
57 HANDLE h=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,lgth,NULL);
58 ret=(char *)MapViewOfFile(h,FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE,0,0,lgth);
62 std::copy(ml.begin(),ml.end(),ret);
66 void INTERP_KERNEL::AsmX86::convertOneInstructionInML(const std::string& inst, std::vector<char>& ml) const
68 std::string::size_type pos=inst.find_first_of(' ');
71 if(pos!=std::string::npos)
73 op=inst.substr(0,pos);
74 param=inst.substr(pos+1);
79 for(const char **it=OPS;it!=OPS+NB_OF_OPS;it++,id++)
91 convertPush(param,ml);
100 convertFaddp(param,ml);
103 convertFsubp(param,ml);
106 convertFmulp(param,ml);
109 convertFdivp(param,ml);
112 convertFcos(param,ml);
115 convertFsin(param,ml);
118 convertFabs(param,ml);
121 convertFchs(param,ml);
124 convertFsqrt(param,ml);
127 convertSub(param,ml);
130 convertAdd(param,ml);
133 convertRet(param,ml);
136 convertLeave(param,ml);
139 convertMovsd(param,ml);
142 convertFst(param,ml);
146 std::ostringstream oss; oss << "Unrecognized op : " << op << " in assembly line : " << inst;
147 throw INTERP_KERNEL::Exception(oss.str().c_str());
154 void INTERP_KERNEL::AsmX86::convertMov(const std::string& inst, std::vector<char>& ml)
156 const char ASM1[]="ebp,esp";
157 const unsigned char ML1[2]={0x89,0xe5};
160 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
163 const char ASM2[]="rbp,rsp";
164 const unsigned char ML2[3]={0x48,0x89,0xe5};
167 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
170 std::string::size_type pos=inst.find_first_of(' ');
171 if(pos==std::string::npos)
173 std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
174 throw INTERP_KERNEL::Exception(oss.str().c_str());
176 std::string inst2=inst.substr(pos+1);
177 pos=inst2.find_first_of(',');
178 if(pos==std::string::npos)
180 std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
181 throw INTERP_KERNEL::Exception(oss.str().c_str());
183 std::string inst3=inst2.substr(0,pos);
184 std::string inst4=inst2.substr(pos+1);
185 convertMovToEsp(inst3,inst4,ml);
188 void INTERP_KERNEL::AsmX86::convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector<char>& ml)
190 if(inst1[0]!='[' || inst1[inst1.length()-1]!=']')
191 throw INTERP_KERNEL::Exception("not recognized convertMovToEsp exp !");
192 std::string inst1bis=inst1.substr(1,inst1.length()-2);
193 const char ASM1[]="esp";
194 const unsigned char ML1[3]={0xc7,0x04,0x24};
196 {//mov dword [esp],0x3ff3c0ca
197 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
198 appendAddress(inst2,4,ml);
201 if(inst1bis.substr(0,3)==ASM1)
204 {//mov dword [esp+4],0x3ff3c0ca
205 const unsigned char ML2[3]={0xc7,0x44,0x24};
206 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
207 std::string::size_type pos=inst1bis.find_first_of(']');
208 std::string inst1_1=inst1bis.substr(4,pos-4-1);
209 appendAddress(inst1_1,1,ml);
210 appendAddress(inst2,4,ml);
214 throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
216 const char ASM3[]="rsp";
217 const unsigned char ML3[3]={0xc7,0x04,0x24};
219 {//mov dword [rsp],0x3ff3c0ca
220 ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
221 appendAddress(inst2,4,ml);
224 if(inst1bis.substr(0,3)==ASM3)
227 {//mov dword [rsp+4],0x3ff3c0ca
228 const unsigned char ML2[3]={0xc7,0x44,0x24};
229 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
230 std::string::size_type pos=inst1bis.find_first_of(']');
231 std::string inst1_1=inst1bis.substr(4,pos-4-1);
232 appendAddress(inst1_1,1,ml);
233 appendAddress(inst2,4,ml);
237 throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
239 throw INTERP_KERNEL::Exception("Not recognized exp : mov");
242 void INTERP_KERNEL::AsmX86::convertPush(const std::string& inst, std::vector<char>& ml)
244 std::string::size_type pos=inst.find_first_of(' ');
245 std::string inst2=inst.substr(pos+1);
246 const char ASM1[]="ebp";
247 const unsigned char ML1[1]={0x55};
250 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
253 const char ASM2[]="ebx";
254 const unsigned char ML2[1]={0x53};
257 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
260 const char ASM3[]="rbp";
261 const unsigned char ML3[1]={0x55};
264 ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
267 throw INTERP_KERNEL::Exception("Unrecognized push instruction");
270 void INTERP_KERNEL::AsmX86::convertPop(const std::string& inst, std::vector<char>& ml)
272 std::string::size_type pos=inst.find_first_of(' ');
273 std::string inst2=inst.substr(pos+1);
274 const char ASM1[]="ebp";
275 const unsigned char ML1[1]={0x5d};
278 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
281 const char ASM2[]="ebx";
282 const unsigned char ML2[1]={0x5b};
285 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
288 throw INTERP_KERNEL::Exception("Unrecognized pop instruction");
291 void INTERP_KERNEL::AsmX86::convertFld(const std::string& inst, std::vector<char>& ml)
293 std::string::size_type pos=inst.find_first_of(' ');
294 std::string params=inst.substr(pos+1);
295 std::string params2=params.substr(1,params.length()-2);
296 if(params2.substr(0,3)=="esp")
298 const unsigned char ML1[3]={0xdd,0x04,0x24};
299 if(params2.length()==3)
301 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
304 pos=params2.find_first_of('+');
305 if(pos!=std::string::npos)
307 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
308 std::string params3=params2.substr(pos+1);
309 appendAddress(params3,1,ml);
312 throw INTERP_KERNEL::Exception("Unrecognized fld esp...");
314 if(params2.substr(0,3)=="ebp")
316 const unsigned char ML2[2]={0xdd,0x45};
317 if(params2.length()==3)
319 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
323 pos=params2.find_first_of('+');
324 if(pos!=std::string::npos)
326 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
327 std::string params3=params2.substr(pos+1);
328 appendAddress(params3,1,ml);
331 throw INTERP_KERNEL::Exception("Unrecognized fld ebp...");
333 if(params2.substr(0,3)=="rsp")
335 const unsigned char ML2[3]={0xdd,0x04,0x24};
336 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));// to improve ! no fully managed !
339 throw INTERP_KERNEL::Exception("Unrecognized fld instruction");
342 void INTERP_KERNEL::AsmX86::convertFaddp(const std::string& inst, std::vector<char>& ml)
344 const unsigned char ML1[2]={0xde,0xc1};
345 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
348 void INTERP_KERNEL::AsmX86::convertFsubp(const std::string& inst, std::vector<char>& ml)
350 const unsigned char ML1[2]={0xde,0xe9};
351 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
354 void INTERP_KERNEL::AsmX86::convertFmulp(const std::string& inst, std::vector<char>& ml)
356 const unsigned char ML1[2]={0xde,0xc9};
357 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
360 void INTERP_KERNEL::AsmX86::convertFdivp(const std::string& inst, std::vector<char>& ml)
362 const unsigned char ML1[2]={0xde,0xf9};
363 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
366 void INTERP_KERNEL::AsmX86::convertFcos(const std::string& inst, std::vector<char>& ml)
368 const unsigned char ML[2]={0xd9,0xff};
369 ml.insert(ml.end(),ML,ML+sizeof(ML));
372 void INTERP_KERNEL::AsmX86::convertFsin(const std::string& inst, std::vector<char>& ml)
374 const unsigned char ML[2]={0xd9,0xfe};
375 ml.insert(ml.end(),ML,ML+sizeof(ML));
378 void INTERP_KERNEL::AsmX86::convertFabs(const std::string& inst, std::vector<char>& ml)
380 const unsigned char ML[2]={0xd9,0xe1};
381 ml.insert(ml.end(),ML,ML+sizeof(ML));
384 void INTERP_KERNEL::AsmX86::convertFchs(const std::string& inst, std::vector<char>& ml)
386 const unsigned char ML[2]={0xd9,0xe0};
387 ml.insert(ml.end(),ML,ML+sizeof(ML));
390 void INTERP_KERNEL::AsmX86::convertFsqrt(const std::string& inst, std::vector<char>& ml)
392 const unsigned char ML[2]={0xd9,0xfa};
393 ml.insert(ml.end(),ML,ML+sizeof(ML));
396 void INTERP_KERNEL::AsmX86::convertSub(const std::string& inst, std::vector<char>& ml)
398 if(inst.substr(0,4)=="esp,")
400 const unsigned char ML[2]={0x81,0xec};
401 ml.insert(ml.end(),ML,ML+sizeof(ML));
402 std::string inst2=inst.substr(4);
403 appendAddress(inst2,4,ml);
406 if(inst.substr(0,4)=="rsp,")
408 const unsigned char ML[4]={0x48,0x83,0xec,0x08};
409 ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
412 throw INTERP_KERNEL::Exception("Not recognized sub instruction.");
415 void INTERP_KERNEL::AsmX86::convertAdd(const std::string& inst, std::vector<char>& ml)
417 if(inst.substr(0,4)=="esp,")
419 const unsigned char ML[2]={0x81,0xc4};
420 ml.insert(ml.end(),ML,ML+sizeof(ML));
421 std::string inst2=inst.substr(4);
422 appendAddress(inst2,4,ml);
425 if(inst.substr(0,4)=="rsp,")
427 const unsigned char ML[4]={0x48,0x83,0xc4,0x08};
428 ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
431 throw INTERP_KERNEL::Exception("Not recognized add instruction.");
434 void INTERP_KERNEL::AsmX86::convertRet(const std::string& inst, std::vector<char>& ml)
436 const unsigned char ML[1]={0xc3};
437 ml.insert(ml.end(),ML,ML+sizeof(ML));
440 void INTERP_KERNEL::AsmX86::convertLeave(const std::string& inst, std::vector<char>& ml)
442 const unsigned char ML[1]={0xc9};
443 ml.insert(ml.end(),ML,ML+sizeof(ML));
446 void INTERP_KERNEL::AsmX86::convertMovsd(const std::string& inst, std::vector<char>& ml)
448 const char ASM1[]="[rsp],xmm0";
449 const unsigned char ML1[5]={0xf2,0x0f,0x11,0x04,0x24};
452 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
455 const char ASM2[]="xmm0,[rsp]";
456 const unsigned char ML2[5]={0xf2,0x0f,0x10,0x04,0x24};
459 ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
462 std::ostringstream oss; oss << "not recognized instruction movsd : " << inst;
463 throw INTERP_KERNEL::Exception(oss.str().c_str());
466 void INTERP_KERNEL::AsmX86::convertFst(const std::string& inst, std::vector<char>& ml)
468 const char ASM1[]="qword [rsp]";
469 const unsigned char ML1[3]={0xdd,0x14,0x24};
472 ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
475 std::ostringstream oss; oss << "not recognized instruction fst : " << inst;
476 throw INTERP_KERNEL::Exception(oss.str().c_str());
481 void INTERP_KERNEL::AsmX86::appendAddress(const std::string& addr, int nbOfByte, std::vector<char>& ml)
485 std::istringstream iss(addr);
488 if(addr[0]=='0' && addr[1]=='x')
492 for(int k=0;k<nbOfByte;k++)