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.


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