Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/med.git] / src / INTERP_KERNEL / ExprEval / InterpKernelAsmX86.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "InterpKernelAsmX86.hxx"
21
22 #include <cstring>
23 #include <sstream>
24 #include <algorithm>
25
26 #ifdef _POSIX_MAPPED_FILES
27 #include <sys/mman.h>
28 #else
29 #ifdef WNT
30 #include <windows.h>
31 #endif
32 #endif
33
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"};
35
36 std::vector<char> INTERP_KERNEL::AsmX86::convertIntoMachineLangage(const std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
37 {
38   std::vector<char> ret;
39   for(std::vector<std::string>::const_iterator iter=asmb.begin();iter!=asmb.end();iter++)
40     convertOneInstructionInML(*iter,ret);
41   return ret;
42 }
43
44 char *INTERP_KERNEL::AsmX86::copyToExecMemZone(const std::vector<char>& ml, unsigned& offset) const
45 {
46   char *ret=0;
47   int lgth=ml.size();
48 #ifdef _POSIX_MAPPED_FILES
49   ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
50 #else
51 #ifdef WNT
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);
54 #endif
55 #endif
56   if(ret)
57     std::copy(ml.begin(),ml.end(),ret);
58   return ret;
59 }
60
61 void INTERP_KERNEL::AsmX86::convertOneInstructionInML(const std::string& inst, std::vector<char>& ml) const throw(INTERP_KERNEL::Exception)
62 {
63   std::string::size_type pos=inst.find_first_of(' ');
64   std::string op;
65   std::string param;
66   if(pos!=std::string::npos)
67     {
68       op=inst.substr(0,pos);
69       param=inst.substr(pos+1);
70     }
71   else
72     op=inst;
73   int id=0;
74   for(const char **it=OPS;it!=OPS+NB_OF_OPS;it++,id++)
75     {
76       std::string tmp(*it);
77       if(op==tmp)
78         break;
79     }
80   switch(id)
81     {
82     case 0:
83       convertMov(param,ml);
84       break;
85     case 1:
86       convertPush(param,ml);
87       break;
88     case 2:
89       convertPop(param,ml);
90       break;
91     case 3:
92       convertFld(param,ml);
93       break;
94     case 4:
95       convertFaddp(param,ml);
96       break;
97     case 5:
98       convertFsubp(param,ml);
99       break;
100     case 6:
101       convertFmulp(param,ml);
102       break;
103     case 7:
104       convertFdivp(param,ml);
105       break;
106     case 8:
107       convertFcos(param,ml);
108       break;
109     case 9:
110       convertFsin(param,ml);
111       break;
112     case 10:
113       convertFabs(param,ml);
114       break;
115     case 11:
116       convertFchs(param,ml);
117       break;
118     case 12:
119       convertFsqrt(param,ml);
120       break;
121     case 13:
122       convertSub(param,ml);
123       break;
124     case 14:
125       convertAdd(param,ml);
126       break;
127     case 15:
128       convertRet(param,ml);
129       break;
130     case 16:
131       convertLeave(param,ml);
132       break;
133     case 17:
134       convertMovsd(param,ml);
135       break;
136     case 18:
137       convertFst(param,ml);
138       break;
139     default:
140       {
141         std::ostringstream oss; oss << "Unrecognized op : " << op << " in assembly line : " << inst;
142         throw INTERP_KERNEL::Exception(oss.str().c_str());
143       }
144     }
145 }
146
147 #include <iostream>
148
149 void INTERP_KERNEL::AsmX86::convertMov(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
150 {
151   const char ASM1[]="ebp,esp";
152   const unsigned char ML1[2]={0x89,0xe5};
153   if(inst==ASM1)
154     {
155       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
156       return ;
157     }
158   const char ASM2[]="rbp,rsp";
159   const unsigned char ML2[3]={0x48,0x89,0xe5};
160   if(inst==ASM2)
161     {
162       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
163       return ;
164     }
165   std::string::size_type pos=inst.find_first_of(' ');
166   if(pos==std::string::npos)
167     {
168       std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
169       throw INTERP_KERNEL::Exception(oss.str().c_str());
170     }
171   std::string inst2=inst.substr(pos+1);
172   pos=inst2.find_first_of(',');
173   if(pos==std::string::npos)
174     {
175       std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
176       throw INTERP_KERNEL::Exception(oss.str().c_str());
177     }
178   std::string inst3=inst2.substr(0,pos);
179   std::string inst4=inst2.substr(pos+1);
180   convertMovToEsp(inst3,inst4,ml);
181 }
182
183 void INTERP_KERNEL::AsmX86::convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
184 {
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};
190   if(inst1bis==ASM1)
191     {//mov dword [esp],0x3ff3c0ca
192       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
193       appendAddress(inst2,4,ml);
194       return ;
195     }
196   if(inst1bis.substr(0,3)==ASM1)
197     {
198       if(inst1bis[3]=='+')
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);
206           return;
207         }
208       else
209         throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
210     }
211   const char ASM3[]="rsp";
212   const unsigned char ML3[3]={0xc7,0x04,0x24};
213   if(inst1bis==ASM3)
214     {//mov dword [rsp],0x3ff3c0ca
215       ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
216       appendAddress(inst2,4,ml);
217       return ;
218     }
219   if(inst1bis.substr(0,3)==ASM3)
220     {
221       if(inst1bis[3]=='+')
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);
229           return;
230         }
231       else
232         throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
233     }
234   throw INTERP_KERNEL::Exception("Not recognized exp : mov");
235 }
236
237 void INTERP_KERNEL::AsmX86::convertPush(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
238 {
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};
243   if(inst2==ASM1)
244     {//push ebp
245       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
246       return ;
247     }
248   const char ASM2[]="ebx";
249   const unsigned char ML2[1]={0x53};
250   if(inst2==ASM2)
251     {//push ebx
252       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
253       return ;
254     }
255   const char ASM3[]="rbp";
256   const unsigned char ML3[1]={0x55};
257   if(inst2==ASM3)
258     {//push rbp
259       ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
260       return ;
261     }
262   throw INTERP_KERNEL::Exception("Unrecognized push instruction");
263 }
264
265 void INTERP_KERNEL::AsmX86::convertPop(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
266 {
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};
271   if(inst2==ASM1)
272     {//push ebp
273       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
274       return ;
275     }
276   const char ASM2[]="ebx";
277   const unsigned char ML2[1]={0x5b};
278   if(inst2==ASM2)
279     {//push ebx
280       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
281       return ;
282     }
283   throw INTERP_KERNEL::Exception("Unrecognized pop instruction");
284 }
285
286 void INTERP_KERNEL::AsmX86::convertFld(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
287 {
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")
292     {
293       const unsigned char ML1[3]={0xdd,0x04,0x24};
294       if(params2.length()==3)
295         {//fld qword [esp]
296           ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
297           return ;
298         }
299       pos=params2.find_first_of('+');
300       if(pos!=std::string::npos)
301         {//fld qword [esp+@]
302           ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
303           std::string params3=params2.substr(pos+1);
304           appendAddress(params3,1,ml);
305           return ;
306         }
307       throw INTERP_KERNEL::Exception("Unrecognized fld esp...");
308     }
309   if(params2.substr(0,3)=="ebp")
310     {
311       const unsigned char ML2[2]={0xdd,0x45};
312       if(params2.length()==3)
313         {//fld qword [ebp]
314           ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
315           ml.push_back(0);
316           return ;
317         }
318       pos=params2.find_first_of('+');
319       if(pos!=std::string::npos)
320         {//fld qword [esp+@]
321           ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
322           std::string params3=params2.substr(pos+1);
323           appendAddress(params3,1,ml);
324           return ;
325         }
326       throw INTERP_KERNEL::Exception("Unrecognized fld ebp...");
327     }
328   if(params2.substr(0,3)=="rsp")
329     {
330       const unsigned char ML2[3]={0xdd,0x04,0x24};
331       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));// to improve ! no fully managed !
332       return ;
333     }
334   throw INTERP_KERNEL::Exception("Unrecognized fld instruction");
335 }
336
337 void INTERP_KERNEL::AsmX86::convertFaddp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
338 {
339   const unsigned char ML1[2]={0xde,0xc1};
340   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
341 }
342
343 void INTERP_KERNEL::AsmX86::convertFsubp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
344 {
345   const unsigned char ML1[2]={0xde,0xe9};
346   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
347 }
348
349 void INTERP_KERNEL::AsmX86::convertFmulp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
350 {
351   const unsigned char ML1[2]={0xde,0xc9};
352   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
353 }
354
355 void INTERP_KERNEL::AsmX86::convertFdivp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
356 {
357   const unsigned char ML1[2]={0xde,0xf9};
358   ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
359 }
360
361 void INTERP_KERNEL::AsmX86::convertFcos(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
362 {
363   const unsigned char ML[2]={0xd9,0xff};
364   ml.insert(ml.end(),ML,ML+sizeof(ML));
365 }
366
367 void INTERP_KERNEL::AsmX86::convertFsin(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
368 {
369   const unsigned char ML[2]={0xd9,0xfe};
370   ml.insert(ml.end(),ML,ML+sizeof(ML));
371 }
372
373 void INTERP_KERNEL::AsmX86::convertFabs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
374 {
375   const unsigned char ML[2]={0xd9,0xe1};
376   ml.insert(ml.end(),ML,ML+sizeof(ML));
377 }
378
379 void INTERP_KERNEL::AsmX86::convertFchs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
380 {
381   const unsigned char ML[2]={0xd9,0xe0};
382   ml.insert(ml.end(),ML,ML+sizeof(ML));
383 }
384
385 void INTERP_KERNEL::AsmX86::convertFsqrt(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
386 {
387   const unsigned char ML[2]={0xd9,0xfa};
388   ml.insert(ml.end(),ML,ML+sizeof(ML));
389 }
390
391 void INTERP_KERNEL::AsmX86::convertSub(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
392 {
393   if(inst.substr(0,4)=="esp,")
394     {
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);
399       return;
400     }
401   if(inst.substr(0,4)=="rsp,")
402     {
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) !!!!
405       return;
406     }
407   throw INTERP_KERNEL::Exception("Not recognized sub instruction.");
408 }
409
410 void INTERP_KERNEL::AsmX86::convertAdd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
411 {
412   if(inst.substr(0,4)=="esp,")
413     {
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);
418       return;
419     }
420   if(inst.substr(0,4)=="rsp,")
421     {
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) !!!!
424       return;
425     }
426   throw INTERP_KERNEL::Exception("Not recognized add instruction.");
427 }
428
429 void INTERP_KERNEL::AsmX86::convertRet(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
430 {
431   const unsigned char ML[1]={0xc3};
432   ml.insert(ml.end(),ML,ML+sizeof(ML));
433 }
434
435 void INTERP_KERNEL::AsmX86::convertLeave(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
436 {
437   const unsigned char ML[1]={0xc9};
438   ml.insert(ml.end(),ML,ML+sizeof(ML));
439 }
440
441 void INTERP_KERNEL::AsmX86::convertMovsd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
442 {
443   const char ASM1[]="[rsp],xmm0";
444   const unsigned char ML1[5]={0xf2,0x0f,0x11,0x04,0x24};
445   if(inst==ASM1)
446     {
447       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
448       return ;
449     }
450   const char ASM2[]="xmm0,[rsp]";
451   const unsigned char ML2[5]={0xf2,0x0f,0x10,0x04,0x24};
452   if(inst==ASM2)
453     {
454       ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
455       return ;
456     }
457   std::ostringstream oss; oss << "not recognized instruction movsd : " << inst;
458   throw INTERP_KERNEL::Exception(oss.str().c_str());
459 }
460
461 void INTERP_KERNEL::AsmX86::convertFst(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
462 {
463   const char ASM1[]="qword [rsp]";
464   const unsigned char ML1[3]={0xdd,0x14,0x24};
465   if(inst==ASM1)
466     {
467       ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
468       return ;
469     }
470   std::ostringstream oss; oss << "not recognized instruction fst : " << inst;
471   throw INTERP_KERNEL::Exception(oss.str().c_str());
472   //tony
473 }
474
475
476 void INTERP_KERNEL::AsmX86::appendAddress(const std::string& addr, int nbOfByte, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
477 {
478   int i,j;
479   char v;
480   std::istringstream iss(addr);
481   if(addr.length()>2)
482     {
483       if(addr[0]=='0' && addr[1]=='x')
484         iss >> std::hex;
485     }
486   iss >> i;
487   for(int k=0;k<nbOfByte;k++)
488     {
489       j=i&255;
490       v=j;
491       ml.push_back(v);
492       i>>=8;
493     }
494 }