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.


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