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