experimental code copy support
[qemu] / target-i386 / translate-copy.c
1 /*
2  *  i386 on i386 translation
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
27 #include <sys/mman.h>
28 #include <sys/ucontext.h>
29
30 #include "cpu.h"
31 #include "exec-all.h"
32 #include "disas.h"
33
34 extern char exec_loop;
35
36 /* operand size */
37 enum {
38     OT_BYTE = 0,
39     OT_WORD,
40     OT_LONG, 
41     OT_QUAD,
42 };
43
44 #define PREFIX_REPZ   0x01
45 #define PREFIX_REPNZ  0x02
46 #define PREFIX_LOCK   0x04
47 #define PREFIX_DATA   0x08
48 #define PREFIX_ADR    0x10
49
50 typedef struct DisasContext {
51     /* current insn context */
52     int override; /* -1 if no override */
53     int prefix;
54     int aflag, dflag;
55     uint8_t *pc; /* pc = eip + cs_base */
56     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
57                    static state change (stop translation) */
58     /* code output */
59     uint8_t *gen_code_ptr;
60     uint8_t *gen_code_start;
61     
62     /* current block context */
63     uint8_t *cs_base; /* base of CS segment */
64     int pe;     /* protected mode */
65     int code32; /* 32 bit code segment */
66     int f_st;   /* currently unused */
67     int vm86;   /* vm86 mode */
68     int cpl;
69     int iopl;
70     struct TranslationBlock *tb;
71 } DisasContext;
72
73 #define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
74
75 #define CPU_SEG 0x64 /* fs override */
76
77 static inline void gb(DisasContext *s, uint32_t val)
78 {
79     *s->gen_code_ptr++ = val;
80 }
81
82 static inline void gw(DisasContext *s, uint32_t val)
83 {
84     *s->gen_code_ptr++ = val;
85     *s->gen_code_ptr++ = val >> 8;
86 }
87
88 static inline void gl(DisasContext *s, uint32_t val)
89 {
90     *s->gen_code_ptr++ = val;
91     *s->gen_code_ptr++ = val >> 8;
92     *s->gen_code_ptr++ = val >> 16;
93     *s->gen_code_ptr++ = val >> 24;
94 }
95
96 static inline void gjmp(DisasContext *s, long val)
97 {
98     gb(s, 0xe9); /* jmp */
99     gl(s, val - (long)(s->gen_code_ptr + 4));
100 }
101
102 static inline void gen_movl_addr_im(DisasContext *s, 
103                                     uint32_t addr, uint32_t val)
104 {
105     gb(s, CPU_SEG); /* seg movl im, addr */
106     gb(s, 0xc7); 
107     gb(s, 0x05);
108     gl(s, addr);
109     gl(s, val);
110 }
111
112 static inline void gen_movw_addr_im(DisasContext *s, 
113                                     uint32_t addr, uint32_t val)
114 {
115     gb(s, CPU_SEG); /* seg movl im, addr */
116     gb(s, 0x66); 
117     gb(s, 0xc7); 
118     gb(s, 0x05);
119     gl(s, addr);
120     gw(s, val);
121 }
122
123
124 static void gen_jmp(DisasContext *s, uint32_t target_eip)
125 {
126     TranslationBlock *tb = s->tb;
127
128     gb(s, 0xe9); /* jmp */
129     tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
130     gl(s, 0);
131
132     tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
133     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
134     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
135     gjmp(s, (long)&exec_loop);
136
137     s->is_jmp = 1;
138 }
139
140 static void gen_jcc(DisasContext *s, int op,
141                     uint32_t target_eip, uint32_t next_eip)
142 {
143     TranslationBlock *tb = s->tb;
144
145     gb(s, 0x0f); /* jcc */
146     gb(s, 0x80 + op);
147     tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
148     gl(s, 0);
149     gb(s, 0xe9); /* jmp */
150     tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
151     gl(s, 0);
152     
153     tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
154     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
155     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
156     gjmp(s, (long)&exec_loop);
157
158     tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
159     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
160     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
161     gjmp(s, (long)&exec_loop);
162
163     s->is_jmp = 1;
164 }
165
166 static void gen_eob(DisasContext *s)
167 {
168     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
169     gjmp(s, (long)&exec_loop);
170
171     s->is_jmp = 1;
172 }
173
174 static inline void gen_lea_modrm(DisasContext *s, int modrm)
175 {
176     int havesib;
177     int base, disp;
178     int index;
179     int scale;
180     int mod, rm, code;
181
182     mod = (modrm >> 6) & 3;
183     rm = modrm & 7;
184
185     if (s->aflag) {
186
187         havesib = 0;
188         base = rm;
189         index = 0;
190         scale = 0;
191         
192         if (base == 4) {
193             havesib = 1;
194             code = ldub_code(s->pc++);
195             scale = (code >> 6) & 3;
196             index = (code >> 3) & 7;
197             base = code & 7;
198         }
199
200         switch (mod) {
201         case 0:
202             if (base == 5) {
203                 base = -1;
204                 disp = ldl_code(s->pc);
205                 s->pc += 4;
206             } else {
207                 disp = 0;
208             }
209             break;
210         case 1:
211             disp = (int8_t)ldub_code(s->pc++);
212             break;
213         default:
214         case 2:
215             disp = ldl_code(s->pc);
216             s->pc += 4;
217             break;
218         }
219         
220     } else {
221         switch (mod) {
222         case 0:
223             if (rm == 6) {
224                 disp = lduw_code(s->pc);
225                 s->pc += 2;
226             } else {
227                 disp = 0;
228             }
229             break;
230         case 1:
231             disp = (int8_t)ldub_code(s->pc++);
232             break;
233         default:
234         case 2:
235             disp = lduw_code(s->pc);
236             s->pc += 2;
237             break;
238         }
239     }
240 }
241
242 static inline void parse_modrm(DisasContext *s, int modrm)
243 {
244     if ((modrm & 0xc0) != 0xc0)
245         gen_lea_modrm(s, modrm);        
246 }
247
248 static inline uint32_t insn_get(DisasContext *s, int ot)
249 {
250     uint32_t ret;
251
252     switch(ot) {
253     case OT_BYTE:
254         ret = ldub_code(s->pc);
255         s->pc++;
256         break;
257     case OT_WORD:
258         ret = lduw_code(s->pc);
259         s->pc += 2;
260         break;
261     default:
262     case OT_LONG:
263         ret = ldl_code(s->pc);
264         s->pc += 4;
265         break;
266     }
267     return ret;
268 }
269
270 /* convert one instruction. s->is_jmp is set if the translation must
271    be stopped.  */
272 static int disas_insn(DisasContext *s)
273 {
274     uint8_t *pc_start, *pc_tmp, *pc_start_insn;
275     int b, prefixes, aflag, dflag, next_eip, val;
276     int ot;
277     int modrm, mod, op;
278
279     pc_start = s->pc;
280     prefixes = 0;
281     aflag = s->code32;
282     dflag = s->code32;
283     s->override = -1;
284  next_byte:
285     b = ldub_code(s->pc);
286     s->pc++;
287     /* check prefixes */
288     switch (b) {
289     case 0xf3:
290         prefixes |= PREFIX_REPZ;
291         goto next_byte;
292     case 0xf2:
293         prefixes |= PREFIX_REPNZ;
294         goto next_byte;
295     case 0xf0:
296         prefixes |= PREFIX_LOCK;
297         goto next_byte;
298     case 0x2e:
299         s->override = R_CS;
300         goto next_byte;
301     case 0x36:
302         s->override = R_SS;
303         goto next_byte;
304     case 0x3e:
305         s->override = R_DS;
306         goto next_byte;
307     case 0x26:
308         s->override = R_ES;
309         goto next_byte;
310     case 0x64:
311         s->override = R_FS;
312         goto next_byte;
313     case 0x65:
314         s->override = R_GS;
315         goto next_byte;
316     case 0x66:
317         prefixes |= PREFIX_DATA;
318         goto next_byte;
319     case 0x67:
320         prefixes |= PREFIX_ADR;
321         goto next_byte;
322     }
323
324     if (prefixes & PREFIX_DATA)
325         dflag ^= 1;
326     if (prefixes & PREFIX_ADR)
327         aflag ^= 1;
328
329     s->prefix = prefixes;
330     s->aflag = aflag;
331     s->dflag = dflag;
332
333     /* lock generation */
334     if (prefixes & PREFIX_LOCK)
335         goto unsupported_op;
336     if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
337         goto unsupported_op;
338
339     pc_start_insn = s->pc - 1;
340     /* now check op code */
341  reswitch:
342     switch(b) {
343     case 0x0f:
344         /**************************/
345         /* extended op code */
346         b = ldub_code(s->pc++) | 0x100;
347         goto reswitch;
348         
349         /**************************/
350         /* arith & logic */
351     case 0x00 ... 0x05:
352     case 0x08 ... 0x0d:
353     case 0x10 ... 0x15:
354     case 0x18 ... 0x1d:
355     case 0x20 ... 0x25:
356     case 0x28 ... 0x2d:
357     case 0x30 ... 0x35:
358     case 0x38 ... 0x3d:
359         {
360             int f;
361             f = (b >> 1) & 3;
362
363             if ((b & 1) == 0)
364                 ot = OT_BYTE;
365             else
366                 ot = dflag ? OT_LONG : OT_WORD;
367             
368             switch(f) {
369             case 0: /* OP Ev, Gv */
370                 modrm = ldub_code(s->pc++);
371                 parse_modrm(s, modrm);
372                 break;
373             case 1: /* OP Gv, Ev */
374                 modrm = ldub_code(s->pc++);
375                 parse_modrm(s, modrm);
376                 break;
377             case 2: /* OP A, Iv */
378                 insn_get(s, ot);
379                 break;
380             }
381         }
382         break;
383
384     case 0x80: /* GRP1 */
385     case 0x81:
386     case 0x83:
387         {
388             if ((b & 1) == 0)
389                 ot = OT_BYTE;
390             else
391                 ot = dflag ? OT_LONG : OT_WORD;
392             
393             modrm = ldub_code(s->pc++);
394             parse_modrm(s, modrm);
395
396             switch(b) {
397             default:
398             case 0x80:
399             case 0x81:
400                 insn_get(s, ot);
401                 break;
402             case 0x83:
403                 insn_get(s, OT_BYTE);
404                 break;
405             }
406         }
407         break;
408
409         /**************************/
410         /* inc, dec, and other misc arith */
411     case 0x40 ... 0x47: /* inc Gv */
412         break;
413     case 0x48 ... 0x4f: /* dec Gv */
414         break;
415     case 0xf6: /* GRP3 */
416     case 0xf7:
417         if ((b & 1) == 0)
418             ot = OT_BYTE;
419         else
420             ot = dflag ? OT_LONG : OT_WORD;
421
422         modrm = ldub_code(s->pc++);
423         op = (modrm >> 3) & 7;
424         parse_modrm(s, modrm);
425
426         switch(op) {
427         case 0: /* test */
428             insn_get(s, ot);
429             break;
430         case 2: /* not */
431             break;
432         case 3: /* neg */
433             break;
434         case 4: /* mul */
435             break;
436         case 5: /* imul */
437             break;
438         case 6: /* div */
439             break;
440         case 7: /* idiv */
441             break;
442         default:
443             goto illegal_op;
444         }
445         break;
446
447     case 0xfe: /* GRP4 */
448     case 0xff: /* GRP5 */
449         if ((b & 1) == 0)
450             ot = OT_BYTE;
451         else
452             ot = dflag ? OT_LONG : OT_WORD;
453
454         modrm = ldub_code(s->pc++);
455         mod = (modrm >> 6) & 3;
456         op = (modrm >> 3) & 7;
457         if (op >= 2 && b == 0xfe) {
458             goto illegal_op;
459         }
460         pc_tmp = s->pc;
461         parse_modrm(s, modrm);
462
463         switch(op) {
464         case 0: /* inc Ev */
465             break;
466         case 1: /* dec Ev */
467             break;
468         case 2: /* call Ev */
469             /* XXX: optimize and handle MEM exceptions specifically
470                fs movl %eax, regs[0] 
471                movl Ev, %eax 
472                pushl next_eip
473                fs movl %eax, eip
474             */
475             goto unsupported_op;
476         case 3: /* lcall Ev */
477             goto unsupported_op;
478         case 4: /* jmp Ev */
479             /* XXX: optimize and handle MEM exceptions specifically
480                fs movl %eax, regs[0] 
481                movl Ev, %eax 
482                fs movl %eax, eip
483             */
484             goto unsupported_op;
485         case 5: /* ljmp Ev */
486             goto unsupported_op;
487         case 6: /* push Ev */
488             break;
489         default:
490             goto illegal_op;
491         }
492         break;
493     case 0xa8: /* test eAX, Iv */
494     case 0xa9:
495         if ((b & 1) == 0)
496             ot = OT_BYTE;
497         else
498             ot = dflag ? OT_LONG : OT_WORD;
499         insn_get(s, ot);
500         break;
501         
502     case 0x98: /* CWDE/CBW */
503         break;
504     case 0x99: /* CDQ/CWD */
505         break;
506     case 0x1af: /* imul Gv, Ev */
507     case 0x69: /* imul Gv, Ev, I */
508     case 0x6b:
509         ot = dflag ? OT_LONG : OT_WORD;
510         modrm = ldub_code(s->pc++);
511         parse_modrm(s, modrm);
512         if (b == 0x69) {
513             insn_get(s, ot);
514         } else if (b == 0x6b) {
515             insn_get(s, OT_BYTE);
516         } else {
517         }
518         break;
519
520     case 0x84: /* test Ev, Gv */
521     case 0x85: 
522         
523     case 0x1c0:
524     case 0x1c1: /* xadd Ev, Gv */
525
526     case 0x1b0:
527     case 0x1b1: /* cmpxchg Ev, Gv */
528
529     case 0x8f: /* pop Ev */
530
531     case 0x88:
532     case 0x89: /* mov Gv, Ev */
533
534     case 0x8a:
535     case 0x8b: /* mov Ev, Gv */
536
537     case 0x1b6: /* movzbS Gv, Eb */
538     case 0x1b7: /* movzwS Gv, Eb */
539     case 0x1be: /* movsbS Gv, Eb */
540     case 0x1bf: /* movswS Gv, Eb */
541
542     case 0x86:
543     case 0x87: /* xchg Ev, Gv */
544
545     case 0xd0:
546     case 0xd1: /* shift Ev,1 */
547
548     case 0xd2:
549     case 0xd3: /* shift Ev,cl */
550
551     case 0x1a5: /* shld cl */
552     case 0x1ad: /* shrd cl */
553
554     case 0x190 ... 0x19f: /* setcc Gv */
555
556     /* XXX: emulate cmov if not available ? */
557     case 0x140 ... 0x14f: /* cmov Gv, Ev */
558
559     case 0x1a3: /* bt Gv, Ev */
560     case 0x1ab: /* bts */
561     case 0x1b3: /* btr */
562     case 0x1bb: /* btc */
563
564     case 0x1bc: /* bsf */
565     case 0x1bd: /* bsr */
566
567         modrm = ldub_code(s->pc++);
568         parse_modrm(s, modrm);
569         break;
570
571     case 0x1c7: /* cmpxchg8b */
572         modrm = ldub_code(s->pc++);
573         mod = (modrm >> 6) & 3;
574         if (mod == 3)
575             goto illegal_op;
576         parse_modrm(s, modrm);
577         break;
578         
579         /**************************/
580         /* push/pop */
581     case 0x50 ... 0x57: /* push */
582     case 0x58 ... 0x5f: /* pop */
583     case 0x60: /* pusha */
584     case 0x61: /* popa */
585         break;
586
587     case 0x68: /* push Iv */
588     case 0x6a:
589         ot = dflag ? OT_LONG : OT_WORD;
590         if (b == 0x68)
591             insn_get(s, ot);
592         else
593             insn_get(s, OT_BYTE);
594         break;
595     case 0xc8: /* enter */
596         lduw_code(s->pc);
597         s->pc += 2;
598         ldub_code(s->pc++);
599         break;
600     case 0xc9: /* leave */
601         break;
602
603     case 0x06: /* push es */
604     case 0x0e: /* push cs */
605     case 0x16: /* push ss */
606     case 0x1e: /* push ds */
607         /* XXX: optimize:
608          push segs[n].selector
609         */
610         goto unsupported_op;
611     case 0x1a0: /* push fs */
612     case 0x1a8: /* push gs */
613         goto unsupported_op;
614     case 0x07: /* pop es */
615     case 0x17: /* pop ss */
616     case 0x1f: /* pop ds */
617         goto unsupported_op;
618     case 0x1a1: /* pop fs */
619     case 0x1a9: /* pop gs */
620         goto unsupported_op;
621     case 0x8e: /* mov seg, Gv */
622         /* XXX: optimize:
623            fs movl r, regs[]
624            movl segs[].selector, r
625            mov r, Gv
626            fs movl regs[], r
627         */
628         goto unsupported_op;
629     case 0x8c: /* mov Gv, seg */
630         goto unsupported_op;
631     case 0xc4: /* les Gv */
632         op = R_ES;
633         goto do_lxx;
634     case 0xc5: /* lds Gv */
635         op = R_DS;
636         goto do_lxx;
637     case 0x1b2: /* lss Gv */
638         op = R_SS;
639         goto do_lxx;
640     case 0x1b4: /* lfs Gv */
641         op = R_FS;
642         goto do_lxx;
643     case 0x1b5: /* lgs Gv */
644         op = R_GS;
645     do_lxx:
646         goto unsupported_op;
647 #if 0
648         /************************/
649         /* floats */
650     case 0xd8 ... 0xdf: 
651         modrm = ldub_code(s->pc++);
652         mod = (modrm >> 6) & 3;
653         rm = modrm & 7;
654         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
655         if (mod != 3) {
656             /* memory op */
657             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
658             switch(op) {
659             case 0x00 ... 0x07: /* fxxxs */
660             case 0x10 ... 0x17: /* fixxxl */
661             case 0x20 ... 0x27: /* fxxxl */
662             case 0x30 ... 0x37: /* fixxx */
663                 {
664                     int op1;
665                     op1 = op & 7;
666
667                     switch(op >> 4) {
668                     case 0:
669                         gen_op_flds_FT0_A0();
670                         break;
671                     case 1:
672                         gen_op_fildl_FT0_A0();
673                         break;
674                     case 2:
675                         gen_op_fldl_FT0_A0();
676                         break;
677                     case 3:
678                     default:
679                         gen_op_fild_FT0_A0();
680                         break;
681                     }
682                     
683                     gen_op_fp_arith_ST0_FT0[op1]();
684                     if (op1 == 3) {
685                         /* fcomp needs pop */
686                         gen_op_fpop();
687                     }
688                 }
689                 break;
690             case 0x08: /* flds */
691             case 0x0a: /* fsts */
692             case 0x0b: /* fstps */
693             case 0x18: /* fildl */
694             case 0x1a: /* fistl */
695             case 0x1b: /* fistpl */
696             case 0x28: /* fldl */
697             case 0x2a: /* fstl */
698             case 0x2b: /* fstpl */
699             case 0x38: /* filds */
700             case 0x3a: /* fists */
701             case 0x3b: /* fistps */
702                 
703                 switch(op & 7) {
704                 case 0:
705                     switch(op >> 4) {
706                     case 0:
707                         gen_op_flds_ST0_A0();
708                         break;
709                     case 1:
710                         gen_op_fildl_ST0_A0();
711                         break;
712                     case 2:
713                         gen_op_fldl_ST0_A0();
714                         break;
715                     case 3:
716                     default:
717                         gen_op_fild_ST0_A0();
718                         break;
719                     }
720                     break;
721                 default:
722                     switch(op >> 4) {
723                     case 0:
724                         gen_op_fsts_ST0_A0();
725                         break;
726                     case 1:
727                         gen_op_fistl_ST0_A0();
728                         break;
729                     case 2:
730                         gen_op_fstl_ST0_A0();
731                         break;
732                     case 3:
733                     default:
734                         gen_op_fist_ST0_A0();
735                         break;
736                     }
737                     if ((op & 7) == 3)
738                         gen_op_fpop();
739                     break;
740                 }
741                 break;
742             case 0x0c: /* fldenv mem */
743                 gen_op_fldenv_A0(s->dflag);
744                 break;
745             case 0x0d: /* fldcw mem */
746                 gen_op_fldcw_A0();
747                 break;
748             case 0x0e: /* fnstenv mem */
749                 gen_op_fnstenv_A0(s->dflag);
750                 break;
751             case 0x0f: /* fnstcw mem */
752                 gen_op_fnstcw_A0();
753                 break;
754             case 0x1d: /* fldt mem */
755                 gen_op_fldt_ST0_A0();
756                 break;
757             case 0x1f: /* fstpt mem */
758                 gen_op_fstt_ST0_A0();
759                 gen_op_fpop();
760                 break;
761             case 0x2c: /* frstor mem */
762                 gen_op_frstor_A0(s->dflag);
763                 break;
764             case 0x2e: /* fnsave mem */
765                 gen_op_fnsave_A0(s->dflag);
766                 break;
767             case 0x2f: /* fnstsw mem */
768                 gen_op_fnstsw_A0();
769                 break;
770             case 0x3c: /* fbld */
771                 gen_op_fbld_ST0_A0();
772                 break;
773             case 0x3e: /* fbstp */
774                 gen_op_fbst_ST0_A0();
775                 gen_op_fpop();
776                 break;
777             case 0x3d: /* fildll */
778                 gen_op_fildll_ST0_A0();
779                 break;
780             case 0x3f: /* fistpll */
781                 gen_op_fistll_ST0_A0();
782                 gen_op_fpop();
783                 break;
784             default:
785                 goto illegal_op;
786             }
787         } else {
788             /* register float ops */
789             opreg = rm;
790
791             switch(op) {
792             case 0x08: /* fld sti */
793                 gen_op_fpush();
794                 gen_op_fmov_ST0_STN((opreg + 1) & 7);
795                 break;
796             case 0x09: /* fxchg sti */
797                 gen_op_fxchg_ST0_STN(opreg);
798                 break;
799             case 0x0a: /* grp d9/2 */
800                 switch(rm) {
801                 case 0: /* fnop */
802                     break;
803                 default:
804                     goto illegal_op;
805                 }
806                 break;
807             case 0x0c: /* grp d9/4 */
808                 switch(rm) {
809                 case 0: /* fchs */
810                     gen_op_fchs_ST0();
811                     break;
812                 case 1: /* fabs */
813                     gen_op_fabs_ST0();
814                     break;
815                 case 4: /* ftst */
816                     gen_op_fldz_FT0();
817                     gen_op_fcom_ST0_FT0();
818                     break;
819                 case 5: /* fxam */
820                     gen_op_fxam_ST0();
821                     break;
822                 default:
823                     goto illegal_op;
824                 }
825                 break;
826             case 0x0d: /* grp d9/5 */
827                 {
828                     switch(rm) {
829                     case 0:
830                         gen_op_fpush();
831                         gen_op_fld1_ST0();
832                         break;
833                     case 1:
834                         gen_op_fpush();
835                         gen_op_fldl2t_ST0();
836                         break;
837                     case 2:
838                         gen_op_fpush();
839                         gen_op_fldl2e_ST0();
840                         break;
841                     case 3:
842                         gen_op_fpush();
843                         gen_op_fldpi_ST0();
844                         break;
845                     case 4:
846                         gen_op_fpush();
847                         gen_op_fldlg2_ST0();
848                         break;
849                     case 5:
850                         gen_op_fpush();
851                         gen_op_fldln2_ST0();
852                         break;
853                     case 6:
854                         gen_op_fpush();
855                         gen_op_fldz_ST0();
856                         break;
857                     default:
858                         goto illegal_op;
859                     }
860                 }
861                 break;
862             case 0x0e: /* grp d9/6 */
863                 switch(rm) {
864                 case 0: /* f2xm1 */
865                     gen_op_f2xm1();
866                     break;
867                 case 1: /* fyl2x */
868                     gen_op_fyl2x();
869                     break;
870                 case 2: /* fptan */
871                     gen_op_fptan();
872                     break;
873                 case 3: /* fpatan */
874                     gen_op_fpatan();
875                     break;
876                 case 4: /* fxtract */
877                     gen_op_fxtract();
878                     break;
879                 case 5: /* fprem1 */
880                     gen_op_fprem1();
881                     break;
882                 case 6: /* fdecstp */
883                     gen_op_fdecstp();
884                     break;
885                 default:
886                 case 7: /* fincstp */
887                     gen_op_fincstp();
888                     break;
889                 }
890                 break;
891             case 0x0f: /* grp d9/7 */
892                 switch(rm) {
893                 case 0: /* fprem */
894                     gen_op_fprem();
895                     break;
896                 case 1: /* fyl2xp1 */
897                     gen_op_fyl2xp1();
898                     break;
899                 case 2: /* fsqrt */
900                     gen_op_fsqrt();
901                     break;
902                 case 3: /* fsincos */
903                     gen_op_fsincos();
904                     break;
905                 case 5: /* fscale */
906                     gen_op_fscale();
907                     break;
908                 case 4: /* frndint */
909                     gen_op_frndint();
910                     break;
911                 case 6: /* fsin */
912                     gen_op_fsin();
913                     break;
914                 default:
915                 case 7: /* fcos */
916                     gen_op_fcos();
917                     break;
918                 }
919                 break;
920             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
921             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
922             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
923                 {
924                     int op1;
925                     
926                     op1 = op & 7;
927                     if (op >= 0x20) {
928                         gen_op_fp_arith_STN_ST0[op1](opreg);
929                         if (op >= 0x30)
930                             gen_op_fpop();
931                     } else {
932                         gen_op_fmov_FT0_STN(opreg);
933                         gen_op_fp_arith_ST0_FT0[op1]();
934                     }
935                 }
936                 break;
937             case 0x02: /* fcom */
938                 gen_op_fmov_FT0_STN(opreg);
939                 gen_op_fcom_ST0_FT0();
940                 break;
941             case 0x03: /* fcomp */
942                 gen_op_fmov_FT0_STN(opreg);
943                 gen_op_fcom_ST0_FT0();
944                 gen_op_fpop();
945                 break;
946             case 0x15: /* da/5 */
947                 switch(rm) {
948                 case 1: /* fucompp */
949                     gen_op_fmov_FT0_STN(1);
950                     gen_op_fucom_ST0_FT0();
951                     gen_op_fpop();
952                     gen_op_fpop();
953                     break;
954                 default:
955                     goto illegal_op;
956                 }
957                 break;
958             case 0x1c:
959                 switch(rm) {
960                 case 0: /* feni (287 only, just do nop here) */
961                     break;
962                 case 1: /* fdisi (287 only, just do nop here) */
963                     break;
964                 case 2: /* fclex */
965                     gen_op_fclex();
966                     break;
967                 case 3: /* fninit */
968                     gen_op_fninit();
969                     break;
970                 case 4: /* fsetpm (287 only, just do nop here) */
971                     break;
972                 default:
973                     goto illegal_op;
974                 }
975                 break;
976             case 0x1d: /* fucomi */
977                 if (s->cc_op != CC_OP_DYNAMIC)
978                     gen_op_set_cc_op(s->cc_op);
979                 gen_op_fmov_FT0_STN(opreg);
980                 gen_op_fucomi_ST0_FT0();
981                 s->cc_op = CC_OP_EFLAGS;
982                 break;
983             case 0x1e: /* fcomi */
984                 if (s->cc_op != CC_OP_DYNAMIC)
985                     gen_op_set_cc_op(s->cc_op);
986                 gen_op_fmov_FT0_STN(opreg);
987                 gen_op_fcomi_ST0_FT0();
988                 s->cc_op = CC_OP_EFLAGS;
989                 break;
990             case 0x2a: /* fst sti */
991                 gen_op_fmov_STN_ST0(opreg);
992                 break;
993             case 0x2b: /* fstp sti */
994                 gen_op_fmov_STN_ST0(opreg);
995                 gen_op_fpop();
996                 break;
997             case 0x2c: /* fucom st(i) */
998                 gen_op_fmov_FT0_STN(opreg);
999                 gen_op_fucom_ST0_FT0();
1000                 break;
1001             case 0x2d: /* fucomp st(i) */
1002                 gen_op_fmov_FT0_STN(opreg);
1003                 gen_op_fucom_ST0_FT0();
1004                 gen_op_fpop();
1005                 break;
1006             case 0x33: /* de/3 */
1007                 switch(rm) {
1008                 case 1: /* fcompp */
1009                     gen_op_fmov_FT0_STN(1);
1010                     gen_op_fcom_ST0_FT0();
1011                     gen_op_fpop();
1012                     gen_op_fpop();
1013                     break;
1014                 default:
1015                     goto illegal_op;
1016                 }
1017                 break;
1018             case 0x3c: /* df/4 */
1019                 switch(rm) {
1020                 case 0:
1021                     gen_op_fnstsw_EAX();
1022                     break;
1023                 default:
1024                     goto illegal_op;
1025                 }
1026                 break;
1027             case 0x3d: /* fucomip */
1028                 if (s->cc_op != CC_OP_DYNAMIC)
1029                     gen_op_set_cc_op(s->cc_op);
1030                 gen_op_fmov_FT0_STN(opreg);
1031                 gen_op_fucomi_ST0_FT0();
1032                 gen_op_fpop();
1033                 s->cc_op = CC_OP_EFLAGS;
1034                 break;
1035             case 0x3e: /* fcomip */
1036                 if (s->cc_op != CC_OP_DYNAMIC)
1037                     gen_op_set_cc_op(s->cc_op);
1038                 gen_op_fmov_FT0_STN(opreg);
1039                 gen_op_fcomi_ST0_FT0();
1040                 gen_op_fpop();
1041                 s->cc_op = CC_OP_EFLAGS;
1042                 break;
1043             case 0x10 ... 0x13: /* fcmovxx */
1044             case 0x18 ... 0x1b:
1045                 {
1046                     int op1;
1047                     const static uint8_t fcmov_cc[8] = {
1048                         (JCC_B << 1),
1049                         (JCC_Z << 1),
1050                         (JCC_BE << 1),
1051                         (JCC_P << 1),
1052                     };
1053                     op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
1054                     gen_setcc(s, op1);
1055                     gen_op_fcmov_ST0_STN_T0(opreg);
1056                 }
1057                 break;
1058             default:
1059                 goto illegal_op;
1060             }
1061         }
1062         break;
1063 #endif
1064         /**************************/
1065         /* mov */
1066     case 0xc6:
1067     case 0xc7: /* mov Ev, Iv */
1068         if ((b & 1) == 0)
1069             ot = OT_BYTE;
1070         else
1071             ot = dflag ? OT_LONG : OT_WORD;
1072         modrm = ldub_code(s->pc++);
1073         parse_modrm(s, modrm);
1074         insn_get(s, ot);
1075         break;
1076
1077     case 0x8d: /* lea */
1078         ot = dflag ? OT_LONG : OT_WORD;
1079         modrm = ldub_code(s->pc++);
1080         mod = (modrm >> 6) & 3;
1081         if (mod == 3)
1082             goto illegal_op;
1083         parse_modrm(s, modrm);
1084         break;
1085         
1086     case 0xa0: /* mov EAX, Ov */
1087     case 0xa1:
1088     case 0xa2: /* mov Ov, EAX */
1089     case 0xa3:
1090         if ((b & 1) == 0)
1091             ot = OT_BYTE;
1092         else
1093             ot = dflag ? OT_LONG : OT_WORD;
1094         if (s->aflag)
1095             insn_get(s, OT_LONG);
1096         else
1097             insn_get(s, OT_WORD);
1098         break;
1099     case 0xd7: /* xlat */
1100         break;
1101     case 0xb0 ... 0xb7: /* mov R, Ib */
1102         insn_get(s, OT_BYTE);
1103         break;
1104     case 0xb8 ... 0xbf: /* mov R, Iv */
1105         ot = dflag ? OT_LONG : OT_WORD;
1106         insn_get(s, ot);
1107         break;
1108
1109     case 0x91 ... 0x97: /* xchg R, EAX */
1110         break;
1111
1112         /************************/
1113         /* shifts */
1114     case 0xc0:
1115     case 0xc1: /* shift Ev,imm */
1116
1117     case 0x1a4: /* shld imm */
1118     case 0x1ac: /* shrd imm */
1119         modrm = ldub_code(s->pc++);
1120         parse_modrm(s, modrm);
1121         ldub_code(s->pc++);
1122         break;
1123         
1124         /************************/
1125         /* string ops */
1126
1127     case 0xa4: /* movsS */
1128     case 0xa5:
1129         break;
1130         
1131     case 0xaa: /* stosS */
1132     case 0xab:
1133         break;
1134
1135     case 0xac: /* lodsS */
1136     case 0xad:
1137         break;
1138
1139     case 0xae: /* scasS */
1140     case 0xaf:
1141         break;
1142
1143     case 0xa6: /* cmpsS */
1144     case 0xa7:
1145         break;
1146
1147     case 0x6c: /* insS */
1148     case 0x6d:
1149         goto unsupported_op;
1150
1151     case 0x6e: /* outsS */
1152     case 0x6f:
1153         goto unsupported_op;
1154
1155         /************************/
1156         /* port I/O */
1157     case 0xe4:
1158     case 0xe5:
1159         goto unsupported_op;
1160
1161     case 0xe6:
1162     case 0xe7:
1163         goto unsupported_op;
1164
1165     case 0xec:
1166     case 0xed:
1167         goto unsupported_op;
1168
1169     case 0xee:
1170     case 0xef:
1171         goto unsupported_op;
1172
1173         /************************/
1174         /* control */
1175 #if 0
1176     case 0xc2: /* ret im */
1177         val = ldsw_code(s->pc);
1178         s->pc += 2;
1179         gen_pop_T0(s);
1180         gen_stack_update(s, val + (2 << s->dflag));
1181         if (s->dflag == 0)
1182             gen_op_andl_T0_ffff();
1183         gen_op_jmp_T0();
1184         gen_eob(s);
1185         break;
1186 #endif
1187
1188     case 0xc3: /* ret */
1189         gb(s, CPU_SEG);
1190         if (!s->dflag)  
1191             gb(s, 0x66); /* d16 */
1192         gb(s, 0x8f); /* pop addr */
1193         gb(s, 0x05);
1194         gl(s, CPU_FIELD_OFFSET(eip));
1195         if (!s->dflag) {
1196             /* reset high bits of EIP */
1197             gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
1198         }
1199         gen_eob(s);
1200         goto no_copy;
1201     case 0xca: /* lret im */
1202     case 0xcb: /* lret */
1203     case 0xcf: /* iret */
1204     case 0x9a: /* lcall im */
1205     case 0xea: /* ljmp im */
1206         goto unsupported_op;
1207
1208     case 0xe8: /* call im */
1209         ot = dflag ? OT_LONG : OT_WORD;
1210         val = insn_get(s, ot);
1211         next_eip = s->pc - s->cs_base;
1212         val += next_eip;
1213         if (s->dflag) {
1214             gb(s, 0x68); /* pushl imm */
1215             gl(s, next_eip);
1216         } else {
1217             gb(s, 0x66); /* pushw imm */
1218             gb(s, 0x68);
1219             gw(s, next_eip);
1220             val &= 0xffff;
1221         }
1222         gen_jmp(s, val);
1223         goto no_copy;
1224     case 0xe9: /* jmp */
1225         ot = dflag ? OT_LONG : OT_WORD;
1226         val = insn_get(s, ot);
1227         val += s->pc - s->cs_base;
1228         if (s->dflag == 0)
1229             val = val & 0xffff;
1230         gen_jmp(s, val);
1231         goto no_copy;
1232     case 0xeb: /* jmp Jb */
1233         val = (int8_t)insn_get(s, OT_BYTE);
1234         val += s->pc - s->cs_base;
1235         if (s->dflag == 0)
1236             val = val & 0xffff;
1237         gen_jmp(s, val);
1238         goto no_copy;
1239     case 0x70 ... 0x7f: /* jcc Jb */
1240         val = (int8_t)insn_get(s, OT_BYTE);
1241         goto do_jcc;
1242     case 0x180 ... 0x18f: /* jcc Jv */
1243         if (dflag) {
1244             val = insn_get(s, OT_LONG);
1245         } else {
1246             val = (int16_t)insn_get(s, OT_WORD); 
1247         }
1248     do_jcc:
1249         next_eip = s->pc - s->cs_base;
1250         val += next_eip;
1251         if (s->dflag == 0)
1252             val &= 0xffff;
1253         gen_jcc(s, b & 0xf, val, next_eip);
1254         goto no_copy;
1255
1256         /************************/
1257         /* flags */
1258     case 0x9c: /* pushf */
1259         /* XXX: put specific code ? */
1260         goto unsupported_op;
1261     case 0x9d: /* popf */
1262         goto unsupported_op;
1263
1264     case 0x9e: /* sahf */
1265     case 0x9f: /* lahf */
1266     case 0xf5: /* cmc */
1267     case 0xf8: /* clc */
1268     case 0xf9: /* stc */
1269     case 0xfc: /* cld */
1270     case 0xfd: /* std */
1271         break;
1272
1273         /************************/
1274         /* bit operations */
1275     case 0x1ba: /* bt/bts/btr/btc Gv, im */
1276         ot = dflag ? OT_LONG : OT_WORD;
1277         modrm = ldub_code(s->pc++);
1278         op = (modrm >> 3) & 7;
1279         parse_modrm(s, modrm);
1280         /* load shift */
1281         ldub_code(s->pc++);
1282         if (op < 4)
1283             goto illegal_op;
1284         break;
1285         /************************/
1286         /* bcd */
1287     case 0x27: /* daa */
1288         break;
1289     case 0x2f: /* das */
1290         break;
1291     case 0x37: /* aaa */
1292         break;
1293     case 0x3f: /* aas */
1294         break;
1295     case 0xd4: /* aam */
1296         ldub_code(s->pc++);
1297         break;
1298     case 0xd5: /* aad */
1299         ldub_code(s->pc++);
1300         break;
1301         /************************/
1302         /* misc */
1303     case 0x90: /* nop */
1304         break;
1305     case 0x9b: /* fwait */
1306         break;
1307     case 0xcc: /* int3 */
1308         goto unsupported_op;
1309     case 0xcd: /* int N */
1310         goto unsupported_op;
1311     case 0xce: /* into */
1312         goto unsupported_op;
1313     case 0xf1: /* icebp (undocumented, exits to external debugger) */
1314         goto unsupported_op;
1315     case 0xfa: /* cli */
1316         goto unsupported_op;
1317     case 0xfb: /* sti */
1318         goto unsupported_op;
1319     case 0x62: /* bound */
1320         modrm = ldub_code(s->pc++);
1321         mod = (modrm >> 6) & 3;
1322         if (mod == 3)
1323             goto illegal_op;
1324         parse_modrm(s, modrm);
1325         break;
1326     case 0x1c8 ... 0x1cf: /* bswap reg */
1327         break;
1328     case 0xd6: /* salc */
1329         break;
1330     case 0xe0: /* loopnz */
1331     case 0xe1: /* loopz */
1332     case 0xe2: /* loop */
1333     case 0xe3: /* jecxz */
1334         goto unsupported_op;
1335
1336     case 0x130: /* wrmsr */
1337     case 0x132: /* rdmsr */
1338         goto unsupported_op;
1339     case 0x131: /* rdtsc */
1340         goto unsupported_op;
1341     case 0x1a2: /* cpuid */
1342         goto unsupported_op;
1343     case 0xf4: /* hlt */
1344         goto unsupported_op;
1345     case 0x100:
1346         goto unsupported_op;
1347     case 0x101:
1348         goto unsupported_op;
1349     case 0x108: /* invd */
1350     case 0x109: /* wbinvd */
1351         goto unsupported_op;
1352     case 0x63: /* arpl */
1353         goto unsupported_op;
1354     case 0x102: /* lar */
1355     case 0x103: /* lsl */
1356         goto unsupported_op;
1357     case 0x118:
1358         goto unsupported_op;
1359     case 0x120: /* mov reg, crN */
1360     case 0x122: /* mov crN, reg */
1361         goto unsupported_op;
1362     case 0x121: /* mov reg, drN */
1363     case 0x123: /* mov drN, reg */
1364         goto unsupported_op;
1365     case 0x106: /* clts */
1366         goto unsupported_op;
1367     default:
1368         goto illegal_op;
1369     }
1370
1371     /* just copy the code */
1372
1373     /* no override yet */
1374     if (!s->dflag)
1375         gb(s, 0x66);
1376     if (!s->aflag)
1377         gb(s, 0x67);
1378     if (prefixes & PREFIX_REPZ)
1379         gb(s, 0xf3);
1380     else if (prefixes & PREFIX_REPNZ)
1381         gb(s, 0xf2);
1382     {
1383         int len, i;
1384         len = s->pc - pc_start_insn;
1385         for(i = 0; i < len; i++) {
1386             *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
1387         }
1388     }
1389  no_copy:
1390     return 0;
1391  illegal_op:
1392  unsupported_op:
1393     /* fall back to slower code gen necessary */
1394     s->pc = pc_start;
1395     return -1;
1396 }
1397
1398 #define GEN_CODE_MAX_SIZE      8192
1399 #define GEN_CODE_MAX_INSN_SIZE 512
1400
1401 static inline int gen_intermediate_code_internal(CPUState *env,
1402                                                  TranslationBlock *tb, 
1403                                                  uint8_t *gen_code_ptr,
1404                                                  int *gen_code_size_ptr,
1405                                                  int search_pc,
1406                                                  uint8_t *tc_ptr)
1407 {
1408     DisasContext dc1, *dc = &dc1;
1409     uint8_t *pc_insn, *pc_start, *gen_code_end;
1410     int flags, ret;
1411     uint8_t *cs_base;
1412
1413     if (env->nb_breakpoints > 0 ||
1414         env->singlestep_enabled)
1415         return -1;
1416     flags = tb->flags;
1417     if (flags & (HF_TF_MASK | HF_ADDSEG_MASK | 
1418                  HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
1419         return -1;
1420     if (!(flags & HF_SS32_MASK))
1421         return -1;
1422     gen_code_end = gen_code_ptr + 
1423         GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1424     dc->gen_code_ptr = gen_code_ptr;
1425     dc->gen_code_start = gen_code_ptr;
1426
1427     /* generate intermediate code */
1428     pc_start = (uint8_t *)tb->pc;
1429     cs_base = (uint8_t *)tb->cs_base;
1430     dc->pc = pc_start;
1431     dc->cs_base = cs_base;
1432     dc->pe = (flags >> HF_PE_SHIFT) & 1;
1433     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
1434     dc->f_st = 0;
1435     dc->vm86 = (flags >> VM_SHIFT) & 1;
1436     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
1437     dc->iopl = (flags >> IOPL_SHIFT) & 3;
1438     dc->tb = tb;
1439     
1440     dc->is_jmp = 0;
1441
1442     for(;;) {
1443         pc_insn = dc->pc;
1444         ret = disas_insn(dc);
1445         if (ret < 0) {
1446             /* unsupported insn */
1447             if (dc->pc == pc_start) {
1448                 /* if first instruction, signal that no copying was done */
1449                 return -1;
1450             } else {
1451                 gen_jmp(dc, dc->pc - dc->cs_base);
1452                 dc->is_jmp = 1;
1453             }
1454         }
1455         if (search_pc) {
1456             /* search pc mode */
1457             if (tc_ptr < dc->gen_code_ptr) {
1458                 env->eip = pc_insn - cs_base;
1459                 return 0;
1460             }
1461         }
1462         /* stop translation if indicated */
1463         if (dc->is_jmp)
1464             break;
1465         /* if too long translation, stop generation */
1466         if (dc->gen_code_ptr >= gen_code_end ||
1467             (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
1468             gen_jmp(dc, dc->pc - dc->cs_base);
1469             break;
1470         }
1471     }
1472     
1473 #ifdef DEBUG_DISAS
1474     if (loglevel) {
1475         fprintf(logfile, "----------------\n");
1476         fprintf(logfile, "IN: COPY: %s\n", lookup_symbol(pc_start));
1477         disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32);
1478         fprintf(logfile, "\n");
1479     }
1480 #endif
1481
1482     if (!search_pc) {
1483         *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
1484         tb->size = dc->pc - pc_start;
1485         tb->cflags = CF_CODE_COPY;
1486         return 0;
1487     } else {
1488         return -1;
1489     }
1490 }
1491
1492 /* generate code by just copying data. Return -1 if cannot generate
1493    any code. Return 0 if code was generated */
1494 int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
1495                       int max_code_size, int *gen_code_size_ptr)
1496 {
1497     /* generate machine code */
1498     tb->tb_next_offset[0] = 0xffff;
1499     tb->tb_next_offset[1] = 0xffff;
1500 #ifdef USE_DIRECT_JUMP
1501     /* the following two entries are optional (only used for string ops) */
1502     tb->tb_jmp_offset[2] = 0xffff;
1503     tb->tb_jmp_offset[3] = 0xffff;
1504 #endif
1505     return gen_intermediate_code_internal(env, tb, 
1506                                           tb->tc_ptr, gen_code_size_ptr,
1507                                           0, NULL);
1508 }
1509
1510 static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
1511
1512 int cpu_restore_state_copy(TranslationBlock *tb, 
1513                            CPUState *env, unsigned long searched_pc,
1514                            void *puc)
1515 {
1516     struct ucontext *uc = puc;
1517     int ret, eflags;
1518
1519     /* find opc index corresponding to search_pc */
1520     if (searched_pc < (unsigned long)tb->tc_ptr)
1521         return -1;
1522     searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
1523     ret = gen_intermediate_code_internal(env, tb, 
1524                                          dummy_gen_code_buf, NULL,
1525                                          1, (uint8_t *)searched_pc);
1526     if (ret < 0)
1527         return ret;
1528     /* restore all the CPU state from the CPU context from the
1529        signal */
1530     
1531     env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
1532     env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
1533     env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
1534     env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
1535     env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
1536     env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
1537     env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
1538     env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
1539     eflags = uc->uc_mcontext.gregs[REG_EFL];
1540     env->df = 1 - (2 * ((eflags >> 10) & 1));
1541     env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1542     env->cc_op = CC_OP_EFLAGS;
1543     return 0;
1544 }