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