Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


6b1925eb3f2da57e7be3c2ce31d7baf2be73cf1a
[palacios.git] / palacios / src / palacios / vmm_emulator.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_emulator.h>
22 #include <palacios/vm_guest_mem.h>
23 #include <palacios/vmm_decoder.h>
24 #include <palacios/vmm_paging.h>
25 #include <palacios/vmm_instr_emulator.h>
26
27 #ifndef DEBUG_EMULATOR
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33
34
35 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size);
36
37 // We emulate up to the next 4KB page boundry
38 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
39                                    addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
40                                    int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
41                                    void * priv_data) {
42   uint_t emulation_length = 0;
43   addr_t tmp_rcx = 0;
44   addr_t src_addr = 0;
45
46   if (dec_instr->dst_operand.operand != write_gva) {
47     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
48                (void *)dec_instr->dst_operand.operand, (void *)write_gva);
49     return -1;
50   }
51   
52   emulation_length = ( (dec_instr->str_op_length  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? 
53                        dec_instr->str_op_length :
54                        (0x1000 - PAGE_OFFSET_4KB(write_gva)));
55   
56   /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
57   tmp_rcx = emulation_length;
58   
59
60
61
62   if (dec_instr->op_type == V3_OP_MOVS) {
63
64   // figure out addresses here....
65   if (info->mem_mode == PHYSICAL_MEM) {
66     if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
67       PrintError("Could not translate write Source (Physical) to host VA\n");
68       return -1;
69     }
70   } else {
71     if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
72       PrintError("Could not translate write Source (Virtual) to host VA\n");
73       return -1;
74     }
75   }
76
77     if (dec_instr->dst_operand.size == 1) {
78       movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
79     } else if (dec_instr->dst_operand.size == 2) {
80       movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
81     } else if (dec_instr->dst_operand.size == 4) {
82       movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
83 #ifdef __V3_64BIT__
84     } else if (dec_instr->dst_operand.size == 8) {
85       movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
86 #endif
87     } else {
88       PrintError("Invalid operand length\n");
89       return -1;
90     }
91
92     info->vm_regs.rdi += emulation_length;
93     info->vm_regs.rsi += emulation_length;
94
95     // RCX is only modified if the rep prefix is present
96     if (dec_instr->prefixes.rep == 1) {
97       info->vm_regs.rcx -= emulation_length;
98     }
99
100   } else if (dec_instr->op_type == V3_OP_STOS) {
101
102     if (dec_instr->dst_operand.size == 1) {
103       stos8((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
104     } else if (dec_instr->dst_operand.size == 2) {
105       stos16((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
106     } else if (dec_instr->dst_operand.size == 4) {
107       stos32((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
108 #ifdef __V3_64BIT__
109     } else if (dec_instr->dst_operand.size == 8) {
110       stos64((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
111 #endif
112     } else {
113       PrintError("Invalid operand length\n");
114       return -1;
115     }
116
117     info->vm_regs.rdi += emulation_length;
118     
119     // RCX is only modified if the rep prefix is present
120     if (dec_instr->prefixes.rep == 1) {
121       info->vm_regs.rcx -= emulation_length;
122     }
123
124   } else {
125     PrintError("Unimplemented String operation\n");
126     return -1;
127   }
128
129   if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
130     PrintError("Did not fully read hooked data\n");
131     return -1;
132   }
133
134   if (emulation_length == dec_instr->str_op_length) {
135     info->rip += dec_instr->instr_length;
136   }
137
138   return emulation_length;
139 }
140
141
142 static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
143                                  addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
144                                  int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
145                                  void * priv_data) {
146   addr_t src_addr = 0;
147   addr_t em_dst_addr = 0;
148   int src_op_len = 0;
149   int dst_op_len = 0;  
150   PrintDebug("Emulating XCHG write\n");
151
152   if (dec_instr->src_operand.type == MEM_OPERAND) {
153     if (dec_instr->src_operand.operand != write_gva) {
154       PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
155                  (void *)dec_instr->src_operand.operand, (void *)write_gva);
156       return -1;
157     }
158     
159     src_addr = dst_addr;
160   } else if (dec_instr->src_operand.type == REG_OPERAND) {
161     src_addr = dec_instr->src_operand.operand;
162   } else {
163     src_addr = (addr_t)&(dec_instr->src_operand.operand);
164   }
165
166
167
168   if (dec_instr->dst_operand.type == MEM_OPERAND) {
169     if (dec_instr->dst_operand.operand != write_gva) {
170       PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
171                  (void *)dec_instr->dst_operand.operand, (void *)write_gva);
172       return -1;
173     }
174     
175     em_dst_addr = dst_addr;
176   } else if (dec_instr->src_operand.type == REG_OPERAND) {
177     em_dst_addr = dec_instr->src_operand.operand;
178   } else {
179     em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
180   }
181
182   dst_op_len = dec_instr->dst_operand.size;
183   src_op_len = dec_instr->src_operand.size;
184
185   PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
186              (void *)dst_addr, (void *)src_addr);
187
188
189   if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
190     PrintError("Instruction Emulation Failed\n");
191     return -1;
192   }
193
194   if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
195     PrintError("Did not fully write hooked data\n");
196     return -1;
197   }
198
199   info->rip += dec_instr->instr_length;
200
201   return dst_op_len;
202 }
203
204
205
206 static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr, 
207                                 addr_t read_gva, addr_t read_gpa, addr_t src_addr, 
208                                 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), 
209                                 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),                        
210                                 void * priv_data) {
211   addr_t em_src_addr = 0;
212   addr_t em_dst_addr = 0;
213   int src_op_len = 0;
214   int dst_op_len = 0;
215
216   PrintDebug("Emulating XCHG Read\n");
217
218   if (dec_instr->src_operand.type == MEM_OPERAND) {
219     if (dec_instr->src_operand.operand != read_gva) {
220       PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
221                  (void *)dec_instr->src_operand.operand, (void *)read_gva);
222       return -1;
223     }
224     
225     em_src_addr = src_addr;
226   } else if (dec_instr->src_operand.type == REG_OPERAND) {
227     em_src_addr = dec_instr->src_operand.operand;
228   } else {
229     em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
230   }
231
232
233
234   if (dec_instr->dst_operand.type == MEM_OPERAND) {
235     if (dec_instr->dst_operand.operand != read_gva) {
236       PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
237                  (void *)dec_instr->dst_operand.operand, (void *)read_gva);
238       return -1;
239     }
240     
241     em_dst_addr = src_addr;
242   } else if (dec_instr->src_operand.type == REG_OPERAND) {
243     em_dst_addr = dec_instr->src_operand.operand;
244   } else {
245     em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
246   }
247
248   dst_op_len = dec_instr->dst_operand.size;
249   src_op_len = dec_instr->src_operand.size;
250
251   PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
252              (void *)em_dst_addr, (void *)em_src_addr);
253
254
255   if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
256     PrintError("Did not fully read hooked data\n");
257     return -1;
258   }
259
260   if (run_op(info, dec_instr->op_type, em_src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
261     PrintError("Instruction Emulation Failed\n");
262     return -1;
263   }
264
265   if (write_fn(read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) {
266     PrintError("Did not fully write hooked data\n");
267     return -1;
268   }
269
270   info->rip += dec_instr->instr_length;
271
272   return dst_op_len;
273 }
274
275
276
277
278 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa,  addr_t dst_addr, 
279                        int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
280                        void * priv_data) {
281   struct x86_instr dec_instr;
282   uchar_t instr[15];
283   int ret = 0;
284   addr_t src_addr = 0;
285   int src_op_len = 0;
286   int dst_op_len = 0;
287
288   PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
289   PrintDebug("GVA=%p\n", (void *)write_gva);
290
291   if (info->mem_mode == PHYSICAL_MEM) { 
292     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
293   } else { 
294     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
295   }
296
297   if (ret == -1) {
298     return -1;
299   }
300
301   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
302     PrintError("Decoding Error\n");
303     // Kick off single step emulator
304     return -1;
305   }
306   
307   /* 
308    * Instructions needing to be special cased.... *
309    */
310   if (dec_instr.is_str_op) {
311     return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
312   } else if (dec_instr.op_type == V3_OP_XCHG) {
313     return emulate_xchg_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
314   }
315
316
317
318   if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
319       (dec_instr.dst_operand.operand != write_gva)) {
320     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
321                (void *)dec_instr.dst_operand.operand, (void *)write_gva);
322     return -1;
323   }
324
325
326   if (dec_instr.src_operand.type == MEM_OPERAND) {
327     if (info->mem_mode == PHYSICAL_MEM) {
328       if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
329         PrintError("Could not translate write Source (Physical) to host VA\n");
330         return -1;
331       }
332     } else {
333       if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
334         PrintError("Could not translate write Source (Virtual) to host VA\n");
335         return -1;
336       }
337     }
338   } else if (dec_instr.src_operand.type == REG_OPERAND) {
339     src_addr = dec_instr.src_operand.operand;
340   } else {
341     src_addr = (addr_t)&(dec_instr.src_operand.operand);
342   }
343
344   dst_op_len = dec_instr.dst_operand.size;
345   src_op_len = dec_instr.src_operand.size;
346
347   PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
348              (void *)dst_addr, (void *)src_addr);
349
350
351   if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
352     PrintError("Instruction Emulation Failed\n");
353     return -1;
354   }
355
356   if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
357     PrintError("Did not fully write hooked data\n");
358     return -1;
359   }
360
361   info->rip += dec_instr.instr_length;
362
363   return dst_op_len;
364 }
365
366
367 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
368                        int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
369                        int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),  
370                        void * priv_data) {
371   struct x86_instr dec_instr;
372   uchar_t instr[15];
373   int ret = 0;
374   addr_t dst_addr = 0;
375   int src_op_len = 0;
376   int dst_op_len = 0;
377
378   PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
379   PrintDebug("GVA=%p\n", (void *)read_gva);
380
381   if (info->mem_mode == PHYSICAL_MEM) { 
382     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
383   } else { 
384     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
385   }
386
387   if (ret == -1) {
388     return -1;
389   }
390
391   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
392     PrintError("Decoding Error\n");
393     // Kick off single step emulator
394     return -1;
395   }
396   
397   if (dec_instr.is_str_op) {
398     PrintError("String operations not implemented on fully hooked regions\n");
399     return -1;
400   } else if (dec_instr.op_type == V3_OP_XCHG) {
401     return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data);
402   }
403
404
405   if ((dec_instr.src_operand.type != MEM_OPERAND) ||
406       (dec_instr.src_operand.operand != read_gva)) {
407     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
408                (void *)dec_instr.src_operand.operand, (void *)read_gva);
409     return -1;
410   }
411
412
413   if (dec_instr.dst_operand.type == MEM_OPERAND) {
414     if (info->mem_mode == PHYSICAL_MEM) {
415       if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
416         PrintError("Could not translate Read Destination (Physical) to host VA\n");
417         return -1;
418       }
419     } else {
420       if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
421         PrintError("Could not translate Read Destination (Virtual) to host VA\n");
422         return -1;
423       }
424     }
425   } else if (dec_instr.dst_operand.type == REG_OPERAND) {
426     dst_addr = dec_instr.dst_operand.operand;
427   } else {
428     dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
429   }
430
431   src_op_len = dec_instr.src_operand.size;
432   dst_op_len = dec_instr.dst_operand.size;
433
434   PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", 
435              (void *)dst_addr, (void *)src_addr);
436
437   if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
438     PrintError("Did not fully read hooked data\n");
439     return -1;
440   }
441
442   if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
443     PrintError("Instruction Emulation Failed\n");
444     return -1;
445   }
446
447   info->rip += dec_instr.instr_length;
448
449   return src_op_len;
450 }
451
452
453
454
455
456
457 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size) {
458
459   if (src_op_size == 1) {
460     PrintDebug("Executing 8 bit instruction\n");
461
462     switch (op_type) {
463     case V3_OP_ADC:
464       adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
465       break;
466     case V3_OP_ADD:
467       add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
468       break;
469     case V3_OP_AND:
470       and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
471       break;
472     case V3_OP_OR:
473       or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
474       break;
475     case V3_OP_XOR:
476       xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
477       break;
478     case V3_OP_SUB:
479       sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
480       break;
481
482     case V3_OP_MOV:
483       mov8((addr_t *)dst_addr, (addr_t *)src_addr);
484       break;
485
486     case V3_OP_MOVZX:
487       movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
488       break;
489     case V3_OP_MOVSX:
490       movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
491       break;
492
493     case V3_OP_NOT:
494       not8((addr_t *)dst_addr);
495       break;
496     case V3_OP_XCHG:
497       xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
498       break;
499       
500
501     case V3_OP_INC:
502       inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
503       break;
504     case V3_OP_DEC:
505       dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
506       break;
507     case V3_OP_NEG:
508       neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
509       break;
510     case V3_OP_SETB:
511       setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
512       break;
513     case V3_OP_SETBE:
514       setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
515       break;
516     case V3_OP_SETL:
517       setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
518       break;
519     case V3_OP_SETLE:
520       setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
521       break;
522     case V3_OP_SETNB:
523       setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
524       break;
525     case V3_OP_SETNBE:
526       setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
527       break;
528     case V3_OP_SETNL:
529       setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
530       break;
531     case V3_OP_SETNLE:
532       setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
533       break;
534     case V3_OP_SETNO:
535       setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
536       break;
537     case V3_OP_SETNP:
538       setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
539       break;
540     case V3_OP_SETNS:
541       setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
542       break;
543     case V3_OP_SETNZ:
544       setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
545       break;
546     case V3_OP_SETO:
547       seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
548       break;
549     case V3_OP_SETP:
550       setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
551       break;
552     case V3_OP_SETS:
553       sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
554       break;
555     case V3_OP_SETZ:
556       setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
557       break;
558
559     default:
560       PrintError("Unknown 8 bit instruction\n");
561       return -1;
562     }
563
564   } else if (src_op_size == 2) {
565     PrintDebug("Executing 16 bit instruction\n");
566
567     switch (op_type) {
568     case V3_OP_ADC:
569       adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
570       break;
571     case V3_OP_ADD:
572       add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
573       break;
574     case V3_OP_AND:
575       and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
576       break;
577     case V3_OP_OR:
578       or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
579       break;
580     case V3_OP_XOR:
581       xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
582       break;
583     case V3_OP_SUB:
584       sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
585       break;
586
587
588     case V3_OP_INC:
589       inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
590       break;
591     case V3_OP_DEC:
592       dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
593       break;
594     case V3_OP_NEG:
595       neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
596       break;
597
598     case V3_OP_MOV:
599       mov16((addr_t *)dst_addr, (addr_t *)src_addr);
600       break;
601     case V3_OP_MOVZX:
602       movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
603       break;
604     case V3_OP_MOVSX:
605       movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
606       break;
607     case V3_OP_NOT:
608       not16((addr_t *)dst_addr);
609       break;
610     case V3_OP_XCHG:
611       xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
612       break;
613       
614     default:
615       PrintError("Unknown 16 bit instruction\n");
616       return -1;
617     }
618
619   } else if (src_op_size == 4) {
620     PrintDebug("Executing 32 bit instruction\n");
621
622     switch (op_type) {
623     case V3_OP_ADC:
624       adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
625       break;
626     case V3_OP_ADD:
627       add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
628       break;
629     case V3_OP_AND:
630       and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
631       break;
632     case V3_OP_OR:
633       or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
634       break;
635     case V3_OP_XOR:
636       xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
637       break;
638     case V3_OP_SUB:
639       sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
640       break;
641
642     case V3_OP_INC:
643       inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
644       break;
645     case V3_OP_DEC:
646       dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
647       break;
648     case V3_OP_NEG:
649       neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
650       break;
651
652     case V3_OP_MOV:
653       mov32((addr_t *)dst_addr, (addr_t *)src_addr);
654       break;
655
656     case V3_OP_NOT:
657       not32((addr_t *)dst_addr);
658       break;
659     case V3_OP_XCHG:
660       xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
661       break;
662       
663     default:
664       PrintError("Unknown 32 bit instruction\n");
665       return -1;
666     }
667
668 #ifdef __V3_64BIT__
669   } else if (src_op_size == 8) {
670     PrintDebug("Executing 64 bit instruction\n");
671
672     switch (op_type) {
673     case V3_OP_ADC:
674       adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
675       break;
676     case V3_OP_ADD:
677       add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
678       break;
679     case V3_OP_AND:
680       and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
681       break;
682     case V3_OP_OR:
683       or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
684       break;
685     case V3_OP_XOR:
686       xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
687       break;
688     case V3_OP_SUB:
689       sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
690       break;
691
692     case V3_OP_INC:
693       inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
694       break;
695     case V3_OP_DEC:
696       dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
697       break;
698     case V3_OP_NEG:
699       neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
700       break;
701
702     case V3_OP_MOV:
703       mov64((addr_t *)dst_addr, (addr_t *)src_addr);
704       break;
705
706     case V3_OP_NOT:
707       not64((addr_t *)dst_addr);
708       break;
709     case V3_OP_XCHG:
710       xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
711       break;
712       
713     default:
714       PrintError("Unknown 64 bit instruction\n");
715       return -1;
716     }
717 #endif
718
719   } else {
720     PrintError("Invalid Operation Size\n");
721     return -1;
722   }
723
724   return 0;
725 }