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.


Virtual Console
[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 CONFIG_DEBUG_EMULATOR
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 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);
34
35 // We emulate up to the next 4KB page boundry
36 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
37                                    addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
38                                    int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
39                                    void * priv_data) {
40     uint_t emulation_length = 0;
41     uint_t emulation_iter_cnt = 0;
42     addr_t tmp_rcx = 0;
43     addr_t src_addr = 0;
44
45     if (dec_instr->dst_operand.operand != write_gva) {
46         PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
47                    (void *)dec_instr->dst_operand.operand, (void *)write_gva);
48         return -1;
49     }
50   
51     /*emulation_length = ( (dec_instr->str_op_length  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? 
52                          dec_instr->str_op_length :
53                          (0x1000 - PAGE_OFFSET_4KB(write_gva)));*/
54      emulation_length = ( (dec_instr->str_op_length * (dec_instr->dst_operand.size)  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? 
55                          dec_instr->str_op_length * dec_instr->dst_operand.size :
56                          (0x1000 - PAGE_OFFSET_4KB(write_gva)));
57   
58     /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
59     emulation_iter_cnt = emulation_length / dec_instr->dst_operand.size;
60     tmp_rcx = emulation_iter_cnt;
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_iter_cnt;
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_iter_cnt;
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 (info->shdw_pg_mode == SHADOW_PAGING) {
154             if (dec_instr->src_operand.operand != write_gva) {
155                 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
156                            (void *)dec_instr->src_operand.operand, (void *)write_gva);
157                 return -1;
158             }
159         }
160
161         src_addr = dst_addr;
162     } else if (dec_instr->src_operand.type == REG_OPERAND) {
163         src_addr = dec_instr->src_operand.operand;
164     } else {
165         src_addr = (addr_t)&(dec_instr->src_operand.operand);
166     }
167
168
169
170     if (dec_instr->dst_operand.type == MEM_OPERAND) {
171         if (info->shdw_pg_mode == SHADOW_PAGING) {
172             if (dec_instr->dst_operand.operand != write_gva) {
173                 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
174                            (void *)dec_instr->dst_operand.operand, (void *)write_gva);
175                 return -1;
176             }
177         } else {
178             //check that the operand (GVA) maps to the the faulting GPA
179         }
180         
181         em_dst_addr = dst_addr;
182     } else if (dec_instr->src_operand.type == REG_OPERAND) {
183         em_dst_addr = dec_instr->src_operand.operand;
184     } else {
185         em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
186     }
187     
188     dst_op_len = dec_instr->dst_operand.size;
189     src_op_len = dec_instr->src_operand.size;
190     
191     PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
192                (void *)dst_addr, (void *)src_addr);
193     
194     
195     if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
196         PrintError("Instruction Emulation Failed\n");
197         return -1;
198     }
199     
200     if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
201         PrintError("Did not fully write hooked data\n");
202         return -1;
203     }
204     
205     info->rip += dec_instr->instr_length;
206     
207     return dst_op_len;
208 }
209     
210
211
212 static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr, 
213                                 addr_t read_gva, addr_t read_gpa, addr_t src_addr, 
214                                 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), 
215                                 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),                        
216                                 void * priv_data) {
217     addr_t em_src_addr = 0;
218     addr_t em_dst_addr = 0;
219     int src_op_len = 0;
220     int dst_op_len = 0;
221
222     PrintDebug("Emulating XCHG Read\n");
223
224     if (dec_instr->src_operand.type == MEM_OPERAND) {
225         if (dec_instr->src_operand.operand != read_gva) {
226             PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
227                        (void *)dec_instr->src_operand.operand, (void *)read_gva);
228             return -1;
229         }
230     
231         em_src_addr = src_addr;
232     } else if (dec_instr->src_operand.type == REG_OPERAND) {
233         em_src_addr = dec_instr->src_operand.operand;
234     } else {
235         em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
236     }
237
238
239
240     if (dec_instr->dst_operand.type == MEM_OPERAND) {
241         if (info->shdw_pg_mode == SHADOW_PAGING) {
242             if (dec_instr->dst_operand.operand != read_gva) {
243                 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
244                            (void *)dec_instr->dst_operand.operand, (void *)read_gva);
245                 return -1;
246             }
247         } else {
248             //check that the operand (GVA) maps to the the faulting GPA
249         }
250
251         em_dst_addr = src_addr;
252     } else if (dec_instr->src_operand.type == REG_OPERAND) {
253         em_dst_addr = dec_instr->src_operand.operand;
254     } else {
255         em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
256     }
257
258     dst_op_len = dec_instr->dst_operand.size;
259     src_op_len = dec_instr->src_operand.size;
260
261     PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
262                (void *)em_dst_addr, (void *)em_src_addr);
263
264
265     if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
266         PrintError("Did not fully read hooked data\n");
267         return -1;
268     }
269
270     if (run_op(info, dec_instr->op_type, em_src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
271         PrintError("Instruction Emulation Failed\n");
272         return -1;
273     }
274
275     if (write_fn(read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) {
276         PrintError("Did not fully write hooked data\n");
277         return -1;
278     }
279
280     info->rip += dec_instr->instr_length;
281
282     return dst_op_len;
283 }
284
285
286
287
288 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa,  addr_t dst_addr, 
289                         int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
290                         void * priv_data) {
291     struct x86_instr dec_instr;
292     uchar_t instr[15];
293     int ret = 0;
294     addr_t src_addr = 0;
295     int src_op_len = 0;
296     int dst_op_len = 0;
297
298     PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
299     PrintDebug("GVA=%p Dst_Addr=%p\n", (void *)write_gva, (void *)dst_addr);
300
301     if (info->mem_mode == PHYSICAL_MEM) { 
302         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
303     } else { 
304         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
305     }
306
307     if (ret == -1) {
308         return -1;
309     }
310
311     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
312         PrintError("Decoding Error\n");
313         // Kick off single step emulator
314         return -1;
315     }
316   
317     /* 
318      * Instructions needing to be special cased.... *
319      */
320     if (dec_instr.is_str_op) {
321         return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
322     } else if (dec_instr.op_type == V3_OP_XCHG) {
323         return emulate_xchg_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
324     }
325
326
327     if (info->shdw_pg_mode == SHADOW_PAGING) {
328         if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
329             (dec_instr.dst_operand.operand != write_gva)) {
330             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
331                        (void *)dec_instr.dst_operand.operand, (void *)write_gva);
332             return -1;
333         }
334     } else {
335         //check that the operand (GVA) maps to the the faulting GPA
336     }
337
338
339     if (dec_instr.src_operand.type == MEM_OPERAND) {
340         if (info->mem_mode == PHYSICAL_MEM) {
341             if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
342                 PrintError("Could not translate write Source (Physical) to host VA\n");
343                 return -1;
344             }
345         } else {
346             if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
347                 PrintError("Could not translate write Source (Virtual) to host VA\n");
348                 return -1;
349             }
350         }
351     } else if (dec_instr.src_operand.type == REG_OPERAND) {
352         src_addr = dec_instr.src_operand.operand;
353     } else {
354         src_addr = (addr_t)&(dec_instr.src_operand.operand);
355     }
356
357     dst_op_len = dec_instr.dst_operand.size;
358     src_op_len = dec_instr.src_operand.size;
359
360     PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
361                (void *)dst_addr, (void *)src_addr);
362
363
364     if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
365         PrintError("Instruction Emulation Failed\n");
366         return -1;
367     }
368
369     if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
370         PrintError("Did not fully write hooked data\n");
371         return -1;
372     }
373
374     info->rip += dec_instr.instr_length;
375
376     return dst_op_len;
377 }
378
379
380 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
381                        int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
382                        int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),  
383                        void * priv_data) {
384     struct x86_instr dec_instr;
385     uchar_t instr[15];
386     int ret = 0;
387     addr_t dst_addr = 0;
388     int src_op_len = 0;
389     int dst_op_len = 0;
390
391     PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
392     PrintDebug("GVA=%p\n", (void *)read_gva);
393
394     if (info->mem_mode == PHYSICAL_MEM) { 
395         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
396     } else { 
397         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
398     }
399     
400     if (ret == -1) {
401         PrintError("Could not read instruction for Emulated Read at %p\n", (void *)(addr_t)(info->rip));
402         return -1;
403     }
404
405
406     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
407         PrintError("Decoding Error\n");
408         // Kick off single step emulator
409         return -1;
410     }
411   
412     if (dec_instr.is_str_op) {
413         PrintError("String operations not implemented on fully hooked regions\n");
414         return -1;
415     } else if (dec_instr.op_type == V3_OP_XCHG) {
416         return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data);
417     }
418
419     if (info->shdw_pg_mode == SHADOW_PAGING) {
420         if ((dec_instr.src_operand.type != MEM_OPERAND) ||
421             (dec_instr.src_operand.operand != read_gva)) {
422             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p operand_type=%d\n",
423                        (void *)dec_instr.src_operand.operand, (void *)read_gva, dec_instr.src_operand.type);
424             return -1;
425         }
426     } else {
427         //check that the operand (GVA) maps to the the faulting GPA
428     }
429
430     if (dec_instr.dst_operand.type == MEM_OPERAND) {
431         if (info->mem_mode == PHYSICAL_MEM) {
432             if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
433                 PrintError("Could not translate Read Destination (Physical) to host VA\n");
434                 return -1;
435             }
436         } else {
437             if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
438                 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
439                 return -1;
440             }
441         }
442     } else if (dec_instr.dst_operand.type == REG_OPERAND) {
443         dst_addr = dec_instr.dst_operand.operand;
444     } else {
445         dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
446     }
447
448     src_op_len = dec_instr.src_operand.size;
449     dst_op_len = dec_instr.dst_operand.size;
450
451     PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", 
452                (void *)dst_addr, (void *)src_addr);
453
454     if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
455         PrintError("Did not fully read hooked data\n");
456         return -1;
457     }
458
459     if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
460         PrintError("Instruction Emulation Failed\n");
461         return -1;
462     }
463
464     info->rip += dec_instr.instr_length;
465
466     return src_op_len;
467 }
468
469
470
471
472
473
474 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) {
475
476     if (src_op_size == 1) {
477         PrintDebug("Executing 8 bit instruction\n");
478
479         switch (op_type) {
480             case V3_OP_ADC:
481                 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
482                 break;
483             case V3_OP_ADD:
484                 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
485                 break;
486             case V3_OP_AND:
487                 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
488                 break;
489             case V3_OP_OR:
490                 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
491                 break;
492             case V3_OP_XOR:
493                 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
494                 break;
495             case V3_OP_SUB:
496                 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
497                 break;
498
499             case V3_OP_MOV:
500                 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
501                 break;
502
503             case V3_OP_MOVZX:
504                 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
505                 break;
506             case V3_OP_MOVSX:
507                 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
508                 break;
509
510             case V3_OP_NOT:
511                 not8((addr_t *)dst_addr);
512                 break;
513             case V3_OP_XCHG:
514                 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
515                 break;
516       
517
518             case V3_OP_INC:
519                 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
520                 break;
521             case V3_OP_DEC:
522                 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
523                 break;
524             case V3_OP_NEG:
525                 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
526                 break;
527             case V3_OP_SETB:
528                 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
529                 break;
530             case V3_OP_SETBE:
531                 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
532                 break;
533             case V3_OP_SETL:
534                 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
535                 break;
536             case V3_OP_SETLE:
537                 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
538                 break;
539             case V3_OP_SETNB:
540                 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
541                 break;
542             case V3_OP_SETNBE:
543                 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
544                 break;
545             case V3_OP_SETNL:
546                 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
547                 break;
548             case V3_OP_SETNLE:
549                 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
550                 break;
551             case V3_OP_SETNO:
552                 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
553                 break;
554             case V3_OP_SETNP:
555                 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
556                 break;
557             case V3_OP_SETNS:
558                 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
559                 break;
560             case V3_OP_SETNZ:
561                 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
562                 break;
563             case V3_OP_SETO:
564                 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
565                 break;
566             case V3_OP_SETP:
567                 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
568                 break;
569             case V3_OP_SETS:
570                 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
571                 break;
572             case V3_OP_SETZ:
573                 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
574                 break;
575
576             default:
577                 PrintError("Unknown 8 bit instruction\n");
578                 return -1;
579         }
580
581     } else if (src_op_size == 2) {
582         PrintDebug("Executing 16 bit instruction\n");
583
584         switch (op_type) {
585             case V3_OP_ADC:
586                 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
587                 break;
588             case V3_OP_ADD:
589                 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
590                 break;
591             case V3_OP_AND:
592                 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
593                 break;
594             case V3_OP_OR:
595                 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
596                 break;
597             case V3_OP_XOR:
598                 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
599                 break;
600             case V3_OP_SUB:
601                 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
602                 break;
603
604
605             case V3_OP_INC:
606                 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
607                 break;
608             case V3_OP_DEC:
609                 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
610                 break;
611             case V3_OP_NEG:
612                 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
613                 break;
614
615             case V3_OP_MOV:
616                 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
617                 break;
618             case V3_OP_MOVZX:
619                 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
620                 break;
621             case V3_OP_MOVSX:
622                 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
623                 break;
624             case V3_OP_NOT:
625                 not16((addr_t *)dst_addr);
626                 break;
627             case V3_OP_XCHG:
628                 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
629                 break;
630       
631             default:
632                 PrintError("Unknown 16 bit instruction\n");
633                 return -1;
634         }
635
636     } else if (src_op_size == 4) {
637         PrintDebug("Executing 32 bit instruction\n");
638
639         switch (op_type) {
640             case V3_OP_ADC:
641                 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
642                 break;
643             case V3_OP_ADD:
644                 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
645                 break;
646             case V3_OP_AND:
647                 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
648                 break;
649             case V3_OP_OR:
650                 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
651                 break;
652             case V3_OP_XOR:
653                 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
654                 break;
655             case V3_OP_SUB:
656                 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
657                 break;
658
659             case V3_OP_INC:
660                 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
661                 break;
662             case V3_OP_DEC:
663                 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
664                 break;
665             case V3_OP_NEG:
666                 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
667                 break;
668
669             case V3_OP_MOV:
670                 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
671                 break;
672
673             case V3_OP_NOT:
674                 not32((addr_t *)dst_addr);
675                 break;
676             case V3_OP_XCHG:
677                 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
678                 break;
679       
680             default:
681                 PrintError("Unknown 32 bit instruction\n");
682                 return -1;
683         }
684
685 #ifdef __V3_64BIT__
686     } else if (src_op_size == 8) {
687         PrintDebug("Executing 64 bit instruction\n");
688
689         switch (op_type) {
690             case V3_OP_ADC:
691                 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
692                 break;
693             case V3_OP_ADD:
694                 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
695                 break;
696             case V3_OP_AND:
697                 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
698                 break;
699             case V3_OP_OR:
700                 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
701                 break;
702             case V3_OP_XOR:
703                 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
704                 break;
705             case V3_OP_SUB:
706                 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
707                 break;
708
709             case V3_OP_INC:
710                 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
711                 break;
712             case V3_OP_DEC:
713                 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
714                 break;
715             case V3_OP_NEG:
716                 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
717                 break;
718
719             case V3_OP_MOV:
720                 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
721                 break;
722
723             case V3_OP_NOT:
724                 not64((addr_t *)dst_addr);
725                 break;
726             case V3_OP_XCHG:
727                 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
728                 break;
729       
730             default:
731                 PrintError("Unknown 64 bit instruction\n");
732                 return -1;
733         }
734 #endif
735
736     } else {
737         PrintError("Invalid Operation Size\n");
738         return -1;
739     }
740
741     return 0;
742 }