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.


e6adab15263207f28f236013b2f599375537d5fb
[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 }