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.


fixes to the emulator to handle nested paging
[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 (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\n", (void *)write_gva);
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         return -1;
402     }
403
404     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
405         PrintError("Decoding Error\n");
406         // Kick off single step emulator
407         return -1;
408     }
409   
410     if (dec_instr.is_str_op) {
411         PrintError("String operations not implemented on fully hooked regions\n");
412         return -1;
413     } else if (dec_instr.op_type == V3_OP_XCHG) {
414         return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data);
415     }
416
417     if (info->shdw_pg_mode == SHADOW_PAGING) {
418         if ((dec_instr.src_operand.type != MEM_OPERAND) ||
419             (dec_instr.src_operand.operand != read_gva)) {
420             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
421                        (void *)dec_instr.src_operand.operand, (void *)read_gva);
422             return -1;
423         }
424     } else {
425         //check that the operand (GVA) maps to the the faulting GPA
426     }
427
428     if (dec_instr.dst_operand.type == MEM_OPERAND) {
429         if (info->mem_mode == PHYSICAL_MEM) {
430             if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
431                 PrintError("Could not translate Read Destination (Physical) to host VA\n");
432                 return -1;
433             }
434         } else {
435             if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
436                 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
437                 return -1;
438             }
439         }
440     } else if (dec_instr.dst_operand.type == REG_OPERAND) {
441         dst_addr = dec_instr.dst_operand.operand;
442     } else {
443         dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
444     }
445
446     src_op_len = dec_instr.src_operand.size;
447     dst_op_len = dec_instr.dst_operand.size;
448
449     PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", 
450                (void *)dst_addr, (void *)src_addr);
451
452     if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
453         PrintError("Did not fully read hooked data\n");
454         return -1;
455     }
456
457     if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
458         PrintError("Instruction Emulation Failed\n");
459         return -1;
460     }
461
462     info->rip += dec_instr.instr_length;
463
464     return src_op_len;
465 }
466
467
468
469
470
471
472 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) {
473
474     if (src_op_size == 1) {
475         PrintDebug("Executing 8 bit instruction\n");
476
477         switch (op_type) {
478             case V3_OP_ADC:
479                 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
480                 break;
481             case V3_OP_ADD:
482                 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
483                 break;
484             case V3_OP_AND:
485                 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
486                 break;
487             case V3_OP_OR:
488                 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
489                 break;
490             case V3_OP_XOR:
491                 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
492                 break;
493             case V3_OP_SUB:
494                 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
495                 break;
496
497             case V3_OP_MOV:
498                 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
499                 break;
500
501             case V3_OP_MOVZX:
502                 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
503                 break;
504             case V3_OP_MOVSX:
505                 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
506                 break;
507
508             case V3_OP_NOT:
509                 not8((addr_t *)dst_addr);
510                 break;
511             case V3_OP_XCHG:
512                 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
513                 break;
514       
515
516             case V3_OP_INC:
517                 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
518                 break;
519             case V3_OP_DEC:
520                 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
521                 break;
522             case V3_OP_NEG:
523                 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
524                 break;
525             case V3_OP_SETB:
526                 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
527                 break;
528             case V3_OP_SETBE:
529                 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
530                 break;
531             case V3_OP_SETL:
532                 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
533                 break;
534             case V3_OP_SETLE:
535                 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
536                 break;
537             case V3_OP_SETNB:
538                 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
539                 break;
540             case V3_OP_SETNBE:
541                 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
542                 break;
543             case V3_OP_SETNL:
544                 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
545                 break;
546             case V3_OP_SETNLE:
547                 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
548                 break;
549             case V3_OP_SETNO:
550                 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
551                 break;
552             case V3_OP_SETNP:
553                 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
554                 break;
555             case V3_OP_SETNS:
556                 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
557                 break;
558             case V3_OP_SETNZ:
559                 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
560                 break;
561             case V3_OP_SETO:
562                 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
563                 break;
564             case V3_OP_SETP:
565                 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
566                 break;
567             case V3_OP_SETS:
568                 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
569                 break;
570             case V3_OP_SETZ:
571                 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
572                 break;
573
574             default:
575                 PrintError("Unknown 8 bit instruction\n");
576                 return -1;
577         }
578
579     } else if (src_op_size == 2) {
580         PrintDebug("Executing 16 bit instruction\n");
581
582         switch (op_type) {
583             case V3_OP_ADC:
584                 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
585                 break;
586             case V3_OP_ADD:
587                 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
588                 break;
589             case V3_OP_AND:
590                 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
591                 break;
592             case V3_OP_OR:
593                 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
594                 break;
595             case V3_OP_XOR:
596                 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
597                 break;
598             case V3_OP_SUB:
599                 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
600                 break;
601
602
603             case V3_OP_INC:
604                 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
605                 break;
606             case V3_OP_DEC:
607                 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
608                 break;
609             case V3_OP_NEG:
610                 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
611                 break;
612
613             case V3_OP_MOV:
614                 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
615                 break;
616             case V3_OP_MOVZX:
617                 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
618                 break;
619             case V3_OP_MOVSX:
620                 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
621                 break;
622             case V3_OP_NOT:
623                 not16((addr_t *)dst_addr);
624                 break;
625             case V3_OP_XCHG:
626                 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
627                 break;
628       
629             default:
630                 PrintError("Unknown 16 bit instruction\n");
631                 return -1;
632         }
633
634     } else if (src_op_size == 4) {
635         PrintDebug("Executing 32 bit instruction\n");
636
637         switch (op_type) {
638             case V3_OP_ADC:
639                 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
640                 break;
641             case V3_OP_ADD:
642                 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
643                 break;
644             case V3_OP_AND:
645                 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
646                 break;
647             case V3_OP_OR:
648                 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
649                 break;
650             case V3_OP_XOR:
651                 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
652                 break;
653             case V3_OP_SUB:
654                 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
655                 break;
656
657             case V3_OP_INC:
658                 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
659                 break;
660             case V3_OP_DEC:
661                 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
662                 break;
663             case V3_OP_NEG:
664                 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
665                 break;
666
667             case V3_OP_MOV:
668                 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
669                 break;
670
671             case V3_OP_NOT:
672                 not32((addr_t *)dst_addr);
673                 break;
674             case V3_OP_XCHG:
675                 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
676                 break;
677       
678             default:
679                 PrintError("Unknown 32 bit instruction\n");
680                 return -1;
681         }
682
683 #ifdef __V3_64BIT__
684     } else if (src_op_size == 8) {
685         PrintDebug("Executing 64 bit instruction\n");
686
687         switch (op_type) {
688             case V3_OP_ADC:
689                 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
690                 break;
691             case V3_OP_ADD:
692                 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
693                 break;
694             case V3_OP_AND:
695                 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
696                 break;
697             case V3_OP_OR:
698                 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
699                 break;
700             case V3_OP_XOR:
701                 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
702                 break;
703             case V3_OP_SUB:
704                 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
705                 break;
706
707             case V3_OP_INC:
708                 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
709                 break;
710             case V3_OP_DEC:
711                 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
712                 break;
713             case V3_OP_NEG:
714                 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
715                 break;
716
717             case V3_OP_MOV:
718                 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
719                 break;
720
721             case V3_OP_NOT:
722                 not64((addr_t *)dst_addr);
723                 break;
724             case V3_OP_XCHG:
725                 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
726                 break;
727       
728             default:
729                 PrintError("Unknown 64 bit instruction\n");
730                 return -1;
731         }
732 #endif
733
734     } else {
735         PrintError("Invalid Operation Size\n");
736         return -1;
737     }
738
739     return 0;
740 }