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.


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