added translation cache
[qemu] / translate-i386.c
1 /*
2  *  i386 translation
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program 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
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <assert.h>
26
27 #define DEBUG_DISAS
28
29 #define IN_OP_I386
30 #include "cpu-i386.h"
31
32 /* dump all code */
33 #ifdef DEBUG_DISAS
34 #include "dis-asm.h"
35 #endif
36
37 static uint8_t *gen_code_ptr;
38 int __op_param1, __op_param2, __op_param3;
39
40 extern FILE *logfile;
41 extern int loglevel;
42
43 /* supress that */
44 static void error(const char *fmt, ...)
45 {
46     va_list ap;
47
48     va_start(ap, fmt);
49     fprintf(stderr, "\n");
50     vfprintf(stderr, fmt, ap);
51     fprintf(stderr, "\n");
52     va_end(ap);
53     exit(1);
54 }
55
56 #define PREFIX_REPZ 1
57 #define PREFIX_REPNZ 2
58 #define PREFIX_LOCK 4
59 #define PREFIX_CS 8
60 #define PREFIX_SS 0x10
61 #define PREFIX_DS 0x20
62 #define PREFIX_ES 0x40
63 #define PREFIX_FS 0x80
64 #define PREFIX_GS 0x100
65 #define PREFIX_DATA 0x200
66 #define PREFIX_ADR 0x400
67 #define PREFIX_FWAIT 0x800
68
69 typedef struct DisasContext {
70     /* current insn context */
71     int prefix;
72     int aflag, dflag;
73     uint8_t *pc; /* current pc */
74     int cc_op; /* current CC operation */
75     int f_st;
76 } DisasContext;
77
78 /* i386 arith/logic operations */
79 enum {
80     OP_ADDL, 
81     OP_ORL, 
82     OP_ADCL, 
83     OP_SBBL,
84     OP_ANDL, 
85     OP_SUBL, 
86     OP_XORL, 
87     OP_CMPL,
88 };
89
90 /* i386 shift ops */
91 enum {
92     OP_ROL, 
93     OP_ROR, 
94     OP_RCL, 
95     OP_RCR, 
96     OP_SHL, 
97     OP_SHR, 
98     OP_SHL1, /* undocumented */
99     OP_SAR = 7,
100 };
101
102 #include "op-i386.h"
103
104 /* operand size */
105 enum {
106     OT_BYTE = 0,
107     OT_WORD,
108     OT_LONG, 
109     OT_QUAD,
110 };
111
112 enum {
113     /* I386 int registers */
114     OR_EAX,   /* MUST be even numbered */
115     OR_ECX,
116     OR_EDX,
117     OR_EBX,
118     OR_ESP,
119     OR_EBP,
120     OR_ESI,
121     OR_EDI,
122     OR_TMP0,    /* temporary operand register */
123     OR_TMP1,
124     OR_A0, /* temporary register used when doing address evaluation */
125     OR_ZERO, /* fixed zero register */
126     NB_OREGS,
127 };
128
129 typedef void (GenOpFunc)(void);
130 typedef void (GenOpFunc1)(long);
131 typedef void (GenOpFunc2)(long, long);
132                     
133 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
134     [OT_BYTE] = {
135         gen_op_movb_EAX_T0,
136         gen_op_movb_ECX_T0,
137         gen_op_movb_EDX_T0,
138         gen_op_movb_EBX_T0,
139         gen_op_movh_EAX_T0,
140         gen_op_movh_ECX_T0,
141         gen_op_movh_EDX_T0,
142         gen_op_movh_EBX_T0,
143     },
144     [OT_WORD] = {
145         gen_op_movw_EAX_T0,
146         gen_op_movw_ECX_T0,
147         gen_op_movw_EDX_T0,
148         gen_op_movw_EBX_T0,
149         gen_op_movw_ESP_T0,
150         gen_op_movw_EBP_T0,
151         gen_op_movw_ESI_T0,
152         gen_op_movw_EDI_T0,
153     },
154     [OT_LONG] = {
155         gen_op_movl_EAX_T0,
156         gen_op_movl_ECX_T0,
157         gen_op_movl_EDX_T0,
158         gen_op_movl_EBX_T0,
159         gen_op_movl_ESP_T0,
160         gen_op_movl_EBP_T0,
161         gen_op_movl_ESI_T0,
162         gen_op_movl_EDI_T0,
163     },
164 };
165
166 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
167     [OT_BYTE] = {
168         gen_op_movb_EAX_T1,
169         gen_op_movb_ECX_T1,
170         gen_op_movb_EDX_T1,
171         gen_op_movb_EBX_T1,
172         gen_op_movh_EAX_T1,
173         gen_op_movh_ECX_T1,
174         gen_op_movh_EDX_T1,
175         gen_op_movh_EBX_T1,
176     },
177     [OT_WORD] = {
178         gen_op_movw_EAX_T1,
179         gen_op_movw_ECX_T1,
180         gen_op_movw_EDX_T1,
181         gen_op_movw_EBX_T1,
182         gen_op_movw_ESP_T1,
183         gen_op_movw_EBP_T1,
184         gen_op_movw_ESI_T1,
185         gen_op_movw_EDI_T1,
186     },
187     [OT_LONG] = {
188         gen_op_movl_EAX_T1,
189         gen_op_movl_ECX_T1,
190         gen_op_movl_EDX_T1,
191         gen_op_movl_EBX_T1,
192         gen_op_movl_ESP_T1,
193         gen_op_movl_EBP_T1,
194         gen_op_movl_ESI_T1,
195         gen_op_movl_EDI_T1,
196     },
197 };
198
199 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
200     [0] = {
201         gen_op_movw_EAX_A0,
202         gen_op_movw_ECX_A0,
203         gen_op_movw_EDX_A0,
204         gen_op_movw_EBX_A0,
205         gen_op_movw_ESP_A0,
206         gen_op_movw_EBP_A0,
207         gen_op_movw_ESI_A0,
208         gen_op_movw_EDI_A0,
209     },
210     [1] = {
211         gen_op_movl_EAX_A0,
212         gen_op_movl_ECX_A0,
213         gen_op_movl_EDX_A0,
214         gen_op_movl_EBX_A0,
215         gen_op_movl_ESP_A0,
216         gen_op_movl_EBP_A0,
217         gen_op_movl_ESI_A0,
218         gen_op_movl_EDI_A0,
219     },
220 };
221
222 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
223 {
224     [OT_BYTE] = {
225         {
226             gen_op_movl_T0_EAX,
227             gen_op_movl_T0_ECX,
228             gen_op_movl_T0_EDX,
229             gen_op_movl_T0_EBX,
230             gen_op_movh_T0_EAX,
231             gen_op_movh_T0_ECX,
232             gen_op_movh_T0_EDX,
233             gen_op_movh_T0_EBX,
234         },
235         {
236             gen_op_movl_T1_EAX,
237             gen_op_movl_T1_ECX,
238             gen_op_movl_T1_EDX,
239             gen_op_movl_T1_EBX,
240             gen_op_movh_T1_EAX,
241             gen_op_movh_T1_ECX,
242             gen_op_movh_T1_EDX,
243             gen_op_movh_T1_EBX,
244         },
245     },
246     [OT_WORD] = {
247         {
248             gen_op_movl_T0_EAX,
249             gen_op_movl_T0_ECX,
250             gen_op_movl_T0_EDX,
251             gen_op_movl_T0_EBX,
252             gen_op_movl_T0_ESP,
253             gen_op_movl_T0_EBP,
254             gen_op_movl_T0_ESI,
255             gen_op_movl_T0_EDI,
256         },
257         {
258             gen_op_movl_T1_EAX,
259             gen_op_movl_T1_ECX,
260             gen_op_movl_T1_EDX,
261             gen_op_movl_T1_EBX,
262             gen_op_movl_T1_ESP,
263             gen_op_movl_T1_EBP,
264             gen_op_movl_T1_ESI,
265             gen_op_movl_T1_EDI,
266         },
267     },
268     [OT_LONG] = {
269         {
270             gen_op_movl_T0_EAX,
271             gen_op_movl_T0_ECX,
272             gen_op_movl_T0_EDX,
273             gen_op_movl_T0_EBX,
274             gen_op_movl_T0_ESP,
275             gen_op_movl_T0_EBP,
276             gen_op_movl_T0_ESI,
277             gen_op_movl_T0_EDI,
278         },
279         {
280             gen_op_movl_T1_EAX,
281             gen_op_movl_T1_ECX,
282             gen_op_movl_T1_EDX,
283             gen_op_movl_T1_EBX,
284             gen_op_movl_T1_ESP,
285             gen_op_movl_T1_EBP,
286             gen_op_movl_T1_ESI,
287             gen_op_movl_T1_EDI,
288         },
289     },
290 };
291
292 static GenOpFunc *gen_op_movl_A0_reg[8] = {
293     gen_op_movl_A0_EAX,
294     gen_op_movl_A0_ECX,
295     gen_op_movl_A0_EDX,
296     gen_op_movl_A0_EBX,
297     gen_op_movl_A0_ESP,
298     gen_op_movl_A0_EBP,
299     gen_op_movl_A0_ESI,
300     gen_op_movl_A0_EDI,
301 };
302
303 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
304     [0] = {
305         gen_op_addl_A0_EAX,
306         gen_op_addl_A0_ECX,
307         gen_op_addl_A0_EDX,
308         gen_op_addl_A0_EBX,
309         gen_op_addl_A0_ESP,
310         gen_op_addl_A0_EBP,
311         gen_op_addl_A0_ESI,
312         gen_op_addl_A0_EDI,
313     },
314     [1] = {
315         gen_op_addl_A0_EAX_s1,
316         gen_op_addl_A0_ECX_s1,
317         gen_op_addl_A0_EDX_s1,
318         gen_op_addl_A0_EBX_s1,
319         gen_op_addl_A0_ESP_s1,
320         gen_op_addl_A0_EBP_s1,
321         gen_op_addl_A0_ESI_s1,
322         gen_op_addl_A0_EDI_s1,
323     },
324     [2] = {
325         gen_op_addl_A0_EAX_s2,
326         gen_op_addl_A0_ECX_s2,
327         gen_op_addl_A0_EDX_s2,
328         gen_op_addl_A0_EBX_s2,
329         gen_op_addl_A0_ESP_s2,
330         gen_op_addl_A0_EBP_s2,
331         gen_op_addl_A0_ESI_s2,
332         gen_op_addl_A0_EDI_s2,
333     },
334     [3] = {
335         gen_op_addl_A0_EAX_s3,
336         gen_op_addl_A0_ECX_s3,
337         gen_op_addl_A0_EDX_s3,
338         gen_op_addl_A0_EBX_s3,
339         gen_op_addl_A0_ESP_s3,
340         gen_op_addl_A0_EBP_s3,
341         gen_op_addl_A0_ESI_s3,
342         gen_op_addl_A0_EDI_s3,
343     },
344 };
345
346 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
347     gen_op_addl_T0_T1_cc,
348     gen_op_orl_T0_T1_cc,
349     NULL,
350     NULL,
351     gen_op_andl_T0_T1_cc,
352     gen_op_subl_T0_T1_cc,
353     gen_op_xorl_T0_T1_cc,
354     gen_op_cmpl_T0_T1_cc,
355 };
356
357 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
358     [OT_BYTE] = {
359         gen_op_adcb_T0_T1_cc,
360         gen_op_sbbb_T0_T1_cc,
361     },
362     [OT_WORD] = {
363         gen_op_adcw_T0_T1_cc,
364         gen_op_sbbw_T0_T1_cc,
365     },
366     [OT_LONG] = {
367         gen_op_adcl_T0_T1_cc,
368         gen_op_sbbl_T0_T1_cc,
369     },
370 };
371
372 static const int cc_op_arithb[8] = {
373     CC_OP_ADDB,
374     CC_OP_LOGICB,
375     CC_OP_ADDB,
376     CC_OP_SUBB,
377     CC_OP_LOGICB,
378     CC_OP_SUBB,
379     CC_OP_LOGICB,
380     CC_OP_SUBB,
381 };
382
383 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
384     [OT_BYTE] = {
385         gen_op_rolb_T0_T1_cc,
386         gen_op_rorb_T0_T1_cc,
387         gen_op_rclb_T0_T1_cc,
388         gen_op_rcrb_T0_T1_cc,
389         gen_op_shlb_T0_T1_cc,
390         gen_op_shrb_T0_T1_cc,
391         gen_op_shlb_T0_T1_cc,
392         gen_op_sarb_T0_T1_cc,
393     },
394     [OT_WORD] = {
395         gen_op_rolw_T0_T1_cc,
396         gen_op_rorw_T0_T1_cc,
397         gen_op_rclw_T0_T1_cc,
398         gen_op_rcrw_T0_T1_cc,
399         gen_op_shlw_T0_T1_cc,
400         gen_op_shrw_T0_T1_cc,
401         gen_op_shlw_T0_T1_cc,
402         gen_op_sarw_T0_T1_cc,
403     },
404     [OT_LONG] = {
405         gen_op_roll_T0_T1_cc,
406         gen_op_rorl_T0_T1_cc,
407         gen_op_rcll_T0_T1_cc,
408         gen_op_rcrl_T0_T1_cc,
409         gen_op_shll_T0_T1_cc,
410         gen_op_shrl_T0_T1_cc,
411         gen_op_shll_T0_T1_cc,
412         gen_op_sarl_T0_T1_cc,
413     },
414 };
415
416 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
417     [0] = {
418         gen_op_shldw_T0_T1_im_cc,
419         gen_op_shrdw_T0_T1_im_cc,
420     },
421     [1] = {
422         gen_op_shldl_T0_T1_im_cc,
423         gen_op_shrdl_T0_T1_im_cc,
424     },
425 };
426
427 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
428     [0] = {
429         gen_op_shldw_T0_T1_ECX_cc,
430         gen_op_shrdw_T0_T1_ECX_cc,
431     },
432     [1] = {
433         gen_op_shldl_T0_T1_ECX_cc,
434         gen_op_shrdl_T0_T1_ECX_cc,
435     },
436 };
437
438 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
439     [0] = {
440         gen_op_btw_T0_T1_cc,
441         gen_op_btsw_T0_T1_cc,
442         gen_op_btrw_T0_T1_cc,
443         gen_op_btcw_T0_T1_cc,
444     },
445     [1] = {
446         gen_op_btl_T0_T1_cc,
447         gen_op_btsl_T0_T1_cc,
448         gen_op_btrl_T0_T1_cc,
449         gen_op_btcl_T0_T1_cc,
450     },
451 };
452
453 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
454     [0] = {
455         gen_op_bsfw_T0_cc,
456         gen_op_bsrw_T0_cc,
457     },
458     [1] = {
459         gen_op_bsfl_T0_cc,
460         gen_op_bsrl_T0_cc,
461     },
462 };
463
464 static GenOpFunc *gen_op_lds_T0_A0[3] = {
465     gen_op_ldsb_T0_A0,
466     gen_op_ldsw_T0_A0,
467 };
468
469 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
470     gen_op_ldub_T0_A0,
471     gen_op_lduw_T0_A0,
472 };
473
474 /* sign does not matter */
475 static GenOpFunc *gen_op_ld_T0_A0[3] = {
476     gen_op_ldub_T0_A0,
477     gen_op_lduw_T0_A0,
478     gen_op_ldl_T0_A0,
479 };
480
481 static GenOpFunc *gen_op_ld_T1_A0[3] = {
482     gen_op_ldub_T1_A0,
483     gen_op_lduw_T1_A0,
484     gen_op_ldl_T1_A0,
485 };
486
487 static GenOpFunc *gen_op_st_T0_A0[3] = {
488     gen_op_stb_T0_A0,
489     gen_op_stw_T0_A0,
490     gen_op_stl_T0_A0,
491 };
492
493 static GenOpFunc *gen_op_movs[6] = {
494     gen_op_movsb,
495     gen_op_movsw,
496     gen_op_movsl,
497     gen_op_rep_movsb,
498     gen_op_rep_movsw,
499     gen_op_rep_movsl,
500 };
501
502 static GenOpFunc *gen_op_stos[6] = {
503     gen_op_stosb,
504     gen_op_stosw,
505     gen_op_stosl,
506     gen_op_rep_stosb,
507     gen_op_rep_stosw,
508     gen_op_rep_stosl,
509 };
510
511 static GenOpFunc *gen_op_lods[6] = {
512     gen_op_lodsb,
513     gen_op_lodsw,
514     gen_op_lodsl,
515     gen_op_rep_lodsb,
516     gen_op_rep_lodsw,
517     gen_op_rep_lodsl,
518 };
519
520 static GenOpFunc *gen_op_scas[9] = {
521     gen_op_scasb,
522     gen_op_scasw,
523     gen_op_scasl,
524     gen_op_repz_scasb,
525     gen_op_repz_scasw,
526     gen_op_repz_scasl,
527     gen_op_repnz_scasb,
528     gen_op_repnz_scasw,
529     gen_op_repnz_scasl,
530 };
531
532 static GenOpFunc *gen_op_cmps[9] = {
533     gen_op_cmpsb,
534     gen_op_cmpsw,
535     gen_op_cmpsl,
536     gen_op_repz_cmpsb,
537     gen_op_repz_cmpsw,
538     gen_op_repz_cmpsl,
539     gen_op_repnz_cmpsb,
540     gen_op_repnz_cmpsw,
541     gen_op_repnz_cmpsl,
542 };
543
544 static GenOpFunc *gen_op_ins[6] = {
545     gen_op_insb,
546     gen_op_insw,
547     gen_op_insl,
548     gen_op_rep_insb,
549     gen_op_rep_insw,
550     gen_op_rep_insl,
551 };
552
553
554 static GenOpFunc *gen_op_outs[6] = {
555     gen_op_outsb,
556     gen_op_outsw,
557     gen_op_outsl,
558     gen_op_rep_outsb,
559     gen_op_rep_outsw,
560     gen_op_rep_outsl,
561 };
562
563 static GenOpFunc *gen_op_in[3] = {
564     gen_op_inb_T0_T1,
565     gen_op_inw_T0_T1,
566     gen_op_inl_T0_T1,
567 };
568
569 static GenOpFunc *gen_op_out[3] = {
570     gen_op_outb_T0_T1,
571     gen_op_outw_T0_T1,
572     gen_op_outl_T0_T1,
573 };
574
575 enum {
576     JCC_O,
577     JCC_B,
578     JCC_Z,
579     JCC_BE,
580     JCC_S,
581     JCC_P,
582     JCC_L,
583     JCC_LE,
584 };
585
586 static GenOpFunc2 *gen_jcc_slow[8] = {
587     gen_op_jo_cc,
588     gen_op_jb_cc,
589     gen_op_jz_cc,
590     gen_op_jbe_cc,
591     gen_op_js_cc,
592     gen_op_jp_cc,
593     gen_op_jl_cc,
594     gen_op_jle_cc,
595 };
596     
597 static GenOpFunc2 *gen_jcc_sub[3][8] = {
598     [OT_BYTE] = {
599         NULL,
600         gen_op_jb_subb,
601         gen_op_jz_subb,
602         gen_op_jbe_subb,
603         gen_op_js_subb,
604         NULL,
605         gen_op_jl_subb,
606         gen_op_jle_subb,
607     },
608     [OT_WORD] = {
609         NULL,
610         gen_op_jb_subw,
611         gen_op_jz_subw,
612         gen_op_jbe_subw,
613         gen_op_js_subw,
614         NULL,
615         gen_op_jl_subw,
616         gen_op_jle_subw,
617     },
618     [OT_LONG] = {
619         NULL,
620         gen_op_jb_subl,
621         gen_op_jz_subl,
622         gen_op_jbe_subl,
623         gen_op_js_subl,
624         NULL,
625         gen_op_jl_subl,
626         gen_op_jle_subl,
627     },
628 };
629
630 static GenOpFunc *gen_setcc_slow[8] = {
631     gen_op_seto_T0_cc,
632     gen_op_setb_T0_cc,
633     gen_op_setz_T0_cc,
634     gen_op_setbe_T0_cc,
635     gen_op_sets_T0_cc,
636     gen_op_setp_T0_cc,
637     gen_op_setl_T0_cc,
638     gen_op_setle_T0_cc,
639 };
640
641 static GenOpFunc *gen_setcc_sub[3][8] = {
642     [OT_BYTE] = {
643         NULL,
644         gen_op_setb_T0_subb,
645         gen_op_setz_T0_subb,
646         gen_op_setbe_T0_subb,
647         gen_op_sets_T0_subb,
648         NULL,
649         gen_op_setl_T0_subb,
650         gen_op_setle_T0_subb,
651     },
652     [OT_WORD] = {
653         NULL,
654         gen_op_setb_T0_subw,
655         gen_op_setz_T0_subw,
656         gen_op_setbe_T0_subw,
657         gen_op_sets_T0_subw,
658         NULL,
659         gen_op_setl_T0_subw,
660         gen_op_setle_T0_subw,
661     },
662     [OT_LONG] = {
663         NULL,
664         gen_op_setb_T0_subl,
665         gen_op_setz_T0_subl,
666         gen_op_setbe_T0_subl,
667         gen_op_sets_T0_subl,
668         NULL,
669         gen_op_setl_T0_subl,
670         gen_op_setle_T0_subl,
671     },
672 };
673
674 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
675     gen_op_fadd_ST0_FT0,
676     gen_op_fmul_ST0_FT0,
677     gen_op_fcom_ST0_FT0,
678     gen_op_fcom_ST0_FT0,
679     gen_op_fsub_ST0_FT0,
680     gen_op_fsubr_ST0_FT0,
681     gen_op_fdiv_ST0_FT0,
682     gen_op_fdivr_ST0_FT0,
683 };
684
685 /* NOTE the exception in "r" op ordering */
686 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
687     gen_op_fadd_STN_ST0,
688     gen_op_fmul_STN_ST0,
689     NULL,
690     NULL,
691     gen_op_fsubr_STN_ST0,
692     gen_op_fsub_STN_ST0,
693     gen_op_fdivr_STN_ST0,
694     gen_op_fdiv_STN_ST0,
695 };
696
697 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
698 {
699     if (d != OR_TMP0)
700         gen_op_mov_TN_reg[ot][0][d]();
701     if (s != OR_TMP1)
702         gen_op_mov_TN_reg[ot][1][s]();
703     if (op == OP_ADCL || op == OP_SBBL) {
704         if (s1->cc_op != CC_OP_DYNAMIC)
705             gen_op_set_cc_op(s1->cc_op);
706         gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
707         s1->cc_op = CC_OP_DYNAMIC;
708     } else {
709         gen_op_arith_T0_T1_cc[op]();
710         s1->cc_op = cc_op_arithb[op] + ot;
711     }
712     if (d != OR_TMP0 && op != OP_CMPL)
713         gen_op_mov_reg_T0[ot][d]();
714 }
715
716 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
717 {
718     gen_op_movl_T1_im(c);
719     gen_op(s1, op, ot, d, OR_TMP1);
720 }
721
722 static void gen_inc(DisasContext *s1, int ot, int d, int c)
723 {
724     if (d != OR_TMP0)
725         gen_op_mov_TN_reg[ot][0][d]();
726     if (s1->cc_op != CC_OP_DYNAMIC)
727         gen_op_set_cc_op(s1->cc_op);
728     if (c > 0) {
729         gen_op_incl_T0_cc();
730         s1->cc_op = CC_OP_INCB + ot;
731     } else {
732         gen_op_decl_T0_cc();
733         s1->cc_op = CC_OP_DECB + ot;
734     }
735     if (d != OR_TMP0)
736         gen_op_mov_reg_T0[ot][d]();
737 }
738
739 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
740 {
741     if (d != OR_TMP0)
742         gen_op_mov_TN_reg[ot][0][d]();
743     if (s != OR_TMP1)
744         gen_op_mov_TN_reg[ot][1][s]();
745     /* for zero counts, flags are not updated, so must do it dynamically */
746     if (s1->cc_op != CC_OP_DYNAMIC)
747         gen_op_set_cc_op(s1->cc_op);
748
749     gen_op_shift_T0_T1_cc[ot][op]();
750
751     if (d != OR_TMP0)
752         gen_op_mov_reg_T0[ot][d]();
753     s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
754 }
755
756 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
757 {
758     /* currently not optimized */
759     gen_op_movl_T1_im(c);
760     gen_shift(s1, op, ot, d, OR_TMP1);
761 }
762
763 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
764 {
765     int havesib;
766     int havebase;
767     int base, disp;
768     int index = 0;
769     int scale = 0;
770     int reg1, reg2, opreg;
771     int mod, rm, code;
772
773     mod = (modrm >> 6) & 3;
774     rm = modrm & 7;
775
776     if (s->aflag) {
777
778         havesib = 0;
779         havebase = 1;
780         base = rm;
781         
782         if (base == 4) {
783             havesib = 1;
784             code = ldub(s->pc++);
785             scale = (code >> 6) & 3;
786             index = (code >> 3) & 7;
787             base = code & 7;
788         }
789
790         switch (mod) {
791         case 0:
792             if (base == 5) {
793                 havebase = 0;
794                 disp = ldl(s->pc);
795                 s->pc += 4;
796             } else {
797                 disp = 0;
798             }
799             break;
800         case 1:
801             disp = (int8_t)ldub(s->pc++);
802             break;
803         default:
804         case 2:
805             disp = ldl(s->pc);
806             s->pc += 4;
807             break;
808         }
809
810         reg1 = OR_ZERO;
811         reg2 = OR_ZERO;
812           
813         if (havebase || (havesib && (index != 4 || scale != 0))) {
814             if (havebase)
815                 reg1 = OR_EAX + base;
816             if (havesib && index != 4) {
817                 if (havebase)
818                     reg2 = index + OR_EAX;
819                 else
820                     reg1 = index + OR_EAX;
821             }
822         }
823         /* XXX: disp only ? */
824         if (reg2 == OR_ZERO) {
825             /* op: disp + (reg1 << scale) */
826             if (reg1 == OR_ZERO) {
827                 gen_op_movl_A0_im(disp);
828             } else if (scale == 0 && disp == 0) {
829                 gen_op_movl_A0_reg[reg1]();
830             } else {
831                 gen_op_movl_A0_im(disp);
832                 gen_op_addl_A0_reg_sN[scale][reg1]();
833             }
834         } else {
835             /* op: disp + reg1 + (reg2 << scale) */
836             if (disp != 0) {
837                 gen_op_movl_A0_im(disp);
838                 gen_op_addl_A0_reg_sN[0][reg1]();
839             } else {
840                 gen_op_movl_A0_reg[reg1]();
841             }
842             gen_op_addl_A0_reg_sN[scale][reg2]();
843         }
844     } else {
845         switch (mod) {
846         case 0:
847             if (rm == 6) {
848                 disp = lduw(s->pc);
849                 s->pc += 2;
850                 gen_op_movl_A0_im(disp);
851                 goto no_rm;
852             } else {
853                 disp = 0;
854             }
855             break;
856         case 1:
857             disp = (int8_t)ldub(s->pc++);
858             break;
859         default:
860         case 2:
861             disp = lduw(s->pc);
862             s->pc += 2;
863             break;
864         }
865         switch(rm) {
866         case 0:
867             gen_op_movl_A0_reg[R_EBX]();
868             gen_op_addl_A0_reg_sN[0][R_ESI]();
869             break;
870         case 1:
871             gen_op_movl_A0_reg[R_EBX]();
872             gen_op_addl_A0_reg_sN[0][R_EDI]();
873             break;
874         case 2:
875             gen_op_movl_A0_reg[R_EBP]();
876             gen_op_addl_A0_reg_sN[0][R_ESI]();
877             break;
878         case 3:
879             gen_op_movl_A0_reg[R_EBP]();
880             gen_op_addl_A0_reg_sN[0][R_EDI]();
881             break;
882         case 4:
883             gen_op_movl_A0_reg[R_ESI]();
884             break;
885         case 5:
886             gen_op_movl_A0_reg[R_EDI]();
887             break;
888         case 6:
889             gen_op_movl_A0_reg[R_EBP]();
890             break;
891         default:
892         case 7:
893             gen_op_movl_A0_reg[R_EBX]();
894             break;
895         }
896         if (disp != 0)
897             gen_op_addl_A0_im(disp);
898         gen_op_andl_A0_ffff();
899     no_rm: ;
900     }
901     opreg = OR_A0;
902     disp = 0;
903     *reg_ptr = opreg;
904     *offset_ptr = disp;
905 }
906
907 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
908    OR_TMP0 */
909 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
910 {
911     int mod, rm, opreg, disp;
912
913     mod = (modrm >> 6) & 3;
914     rm = modrm & 7;
915     if (mod == 3) {
916         if (is_store) {
917             if (reg != OR_TMP0)
918                 gen_op_mov_TN_reg[ot][0][reg]();
919             gen_op_mov_reg_T0[ot][rm]();
920         } else {
921             gen_op_mov_TN_reg[ot][0][rm]();
922             if (reg != OR_TMP0)
923                 gen_op_mov_reg_T0[ot][reg]();
924         }
925     } else {
926         gen_lea_modrm(s, modrm, &opreg, &disp);
927         if (is_store) {
928             if (reg != OR_TMP0)
929                 gen_op_mov_TN_reg[ot][0][reg]();
930             gen_op_st_T0_A0[ot]();
931         } else {
932             gen_op_ld_T0_A0[ot]();
933             if (reg != OR_TMP0)
934                 gen_op_mov_reg_T0[ot][reg]();
935         }
936     }
937 }
938
939 static inline uint32_t insn_get(DisasContext *s, int ot)
940 {
941     uint32_t ret;
942
943     switch(ot) {
944     case OT_BYTE:
945         ret = ldub(s->pc);
946         s->pc++;
947         break;
948     case OT_WORD:
949         ret = lduw(s->pc);
950         s->pc += 2;
951         break;
952     default:
953     case OT_LONG:
954         ret = ldl(s->pc);
955         s->pc += 4;
956         break;
957     }
958     return ret;
959 }
960
961 static void gen_jcc(DisasContext *s, int b, int val)
962 {
963     int inv, jcc_op;
964     GenOpFunc2 *func;
965
966     inv = b & 1;
967     jcc_op = (b >> 1) & 7;
968     switch(s->cc_op) {
969         /* we optimize the cmp/jcc case */
970     case CC_OP_SUBB:
971     case CC_OP_SUBW:
972     case CC_OP_SUBL:
973         func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
974         if (!func)
975             goto slow_jcc;
976         break;
977         
978         /* some jumps are easy to compute */
979     case CC_OP_ADDB:
980     case CC_OP_ADDW:
981     case CC_OP_ADDL:
982     case CC_OP_ADCB:
983     case CC_OP_ADCW:
984     case CC_OP_ADCL:
985     case CC_OP_SBBB:
986     case CC_OP_SBBW:
987     case CC_OP_SBBL:
988     case CC_OP_LOGICB:
989     case CC_OP_LOGICW:
990     case CC_OP_LOGICL:
991     case CC_OP_INCB:
992     case CC_OP_INCW:
993     case CC_OP_INCL:
994     case CC_OP_DECB:
995     case CC_OP_DECW:
996     case CC_OP_DECL:
997     case CC_OP_SHLB:
998     case CC_OP_SHLW:
999     case CC_OP_SHLL:
1000     case CC_OP_SARB:
1001     case CC_OP_SARW:
1002     case CC_OP_SARL:
1003         switch(jcc_op) {
1004         case JCC_Z:
1005             func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1006             break;
1007         case JCC_S:
1008             func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1009             break;
1010         default:
1011             goto slow_jcc;
1012         }
1013         break;
1014     default:
1015     slow_jcc:
1016         if (s->cc_op != CC_OP_DYNAMIC)
1017             gen_op_set_cc_op(s->cc_op);
1018         func = gen_jcc_slow[jcc_op];
1019         break;
1020     }
1021     if (!inv) {
1022         func(val, (long)s->pc);
1023     } else {
1024         func((long)s->pc, val);
1025     }
1026 }
1027
1028 static void gen_setcc(DisasContext *s, int b)
1029 {
1030     int inv, jcc_op;
1031     GenOpFunc *func;
1032
1033     inv = b & 1;
1034     jcc_op = (b >> 1) & 7;
1035     switch(s->cc_op) {
1036         /* we optimize the cmp/jcc case */
1037     case CC_OP_SUBB:
1038     case CC_OP_SUBW:
1039     case CC_OP_SUBL:
1040         func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1041         if (!func)
1042             goto slow_jcc;
1043         break;
1044         
1045         /* some jumps are easy to compute */
1046     case CC_OP_ADDB:
1047     case CC_OP_ADDW:
1048     case CC_OP_ADDL:
1049     case CC_OP_LOGICB:
1050     case CC_OP_LOGICW:
1051     case CC_OP_LOGICL:
1052     case CC_OP_INCB:
1053     case CC_OP_INCW:
1054     case CC_OP_INCL:
1055     case CC_OP_DECB:
1056     case CC_OP_DECW:
1057     case CC_OP_DECL:
1058     case CC_OP_SHLB:
1059     case CC_OP_SHLW:
1060     case CC_OP_SHLL:
1061         switch(jcc_op) {
1062         case JCC_Z:
1063             func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1064             break;
1065         case JCC_S:
1066             func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1067             break;
1068         default:
1069             goto slow_jcc;
1070         }
1071         break;
1072     default:
1073     slow_jcc:
1074         if (s->cc_op != CC_OP_DYNAMIC)
1075             gen_op_set_cc_op(s->cc_op);
1076         func = gen_setcc_slow[jcc_op];
1077         break;
1078     }
1079     func();
1080     if (inv) {
1081         gen_op_xor_T0_1();
1082     }
1083 }
1084
1085 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1086    is set to true if the instruction sets the PC (last instruction of
1087    a basic block) */
1088 long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1089 {
1090     int b, prefixes, aflag, dflag;
1091     int shift, ot;
1092     int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1093
1094     s->pc = pc_start;
1095     prefixes = 0;
1096     aflag = 1;
1097     dflag = 1;
1098     //    cur_pc = s->pc; /* for insn generation */
1099  next_byte:
1100     b = ldub(s->pc);
1101     s->pc++;
1102     /* check prefixes */
1103     switch (b) {
1104     case 0xf3:
1105         prefixes |= PREFIX_REPZ;
1106         goto next_byte;
1107     case 0xf2:
1108         prefixes |= PREFIX_REPNZ;
1109         goto next_byte;
1110     case 0xf0:
1111         prefixes |= PREFIX_LOCK;
1112         goto next_byte;
1113     case 0x2e:
1114         prefixes |= PREFIX_CS;
1115         goto next_byte;
1116     case 0x36:
1117         prefixes |= PREFIX_SS;
1118         goto next_byte;
1119     case 0x3e:
1120         prefixes |= PREFIX_DS;
1121         goto next_byte;
1122     case 0x26:
1123         prefixes |= PREFIX_ES;
1124         goto next_byte;
1125     case 0x64:
1126         prefixes |= PREFIX_FS;
1127         goto next_byte;
1128     case 0x65:
1129         prefixes |= PREFIX_GS;
1130         goto next_byte;
1131     case 0x66:
1132         prefixes |= PREFIX_DATA;
1133         goto next_byte;
1134     case 0x67:
1135         prefixes |= PREFIX_ADR;
1136         goto next_byte;
1137     case 0x9b:
1138         prefixes |= PREFIX_FWAIT;
1139         goto next_byte;
1140     }
1141
1142     if (prefixes & PREFIX_DATA)
1143         dflag ^= 1;
1144     if (prefixes & PREFIX_ADR)
1145         aflag ^= 1;
1146
1147     s->prefix = prefixes;
1148     s->aflag = aflag;
1149     s->dflag = dflag;
1150
1151     /* now check op code */
1152  reswitch:
1153     switch(b) {
1154     case 0x0f:
1155         /**************************/
1156         /* extended op code */
1157         b = ldub(s->pc++) | 0x100;
1158         goto reswitch;
1159         
1160         /**************************/
1161         /* arith & logic */
1162     case 0x00 ... 0x05:
1163     case 0x08 ... 0x0d:
1164     case 0x10 ... 0x15:
1165     case 0x18 ... 0x1d:
1166     case 0x20 ... 0x25:
1167     case 0x28 ... 0x2d:
1168     case 0x30 ... 0x35:
1169     case 0x38 ... 0x3d:
1170         {
1171             int op, f, val;
1172             op = (b >> 3) & 7;
1173             f = (b >> 1) & 3;
1174
1175             if ((b & 1) == 0)
1176                 ot = OT_BYTE;
1177             else
1178                 ot = dflag ? OT_LONG : OT_WORD;
1179             
1180             switch(f) {
1181             case 0: /* OP Ev, Gv */
1182                 modrm = ldub(s->pc++);
1183                 reg = ((modrm >> 3) & 7) + OR_EAX;
1184                 mod = (modrm >> 6) & 3;
1185                 rm = modrm & 7;
1186                 if (mod != 3) {
1187                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1188                     gen_op_ld_T0_A0[ot]();
1189                     opreg = OR_TMP0;
1190                 } else {
1191                     opreg = OR_EAX + rm;
1192                 }
1193                 gen_op(s, op, ot, opreg, reg);
1194                 if (mod != 3 && op != 7) {
1195                     gen_op_st_T0_A0[ot]();
1196                 }
1197                 break;
1198             case 1: /* OP Gv, Ev */
1199                 modrm = ldub(s->pc++);
1200                 mod = (modrm >> 6) & 3;
1201                 reg = ((modrm >> 3) & 7) + OR_EAX;
1202                 rm = modrm & 7;
1203                 if (mod != 3) {
1204                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1205                     gen_op_ld_T1_A0[ot]();
1206                     opreg = OR_TMP1;
1207                 } else {
1208                     opreg = OR_EAX + rm;
1209                 }
1210                 gen_op(s, op, ot, reg, opreg);
1211                 break;
1212             case 2: /* OP A, Iv */
1213                 val = insn_get(s, ot);
1214                 gen_opi(s, op, ot, OR_EAX, val);
1215                 break;
1216             }
1217         }
1218         break;
1219
1220     case 0x80: /* GRP1 */
1221     case 0x81:
1222     case 0x83:
1223         {
1224             int val;
1225
1226             if ((b & 1) == 0)
1227                 ot = OT_BYTE;
1228             else
1229                 ot = dflag ? OT_LONG : OT_WORD;
1230             
1231             modrm = ldub(s->pc++);
1232             mod = (modrm >> 6) & 3;
1233             rm = modrm & 7;
1234             op = (modrm >> 3) & 7;
1235             
1236             if (mod != 3) {
1237                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1238                 gen_op_ld_T0_A0[ot]();
1239                 opreg = OR_TMP0;
1240             } else {
1241                 opreg = rm + OR_EAX;
1242             }
1243
1244             switch(b) {
1245             default:
1246             case 0x80:
1247             case 0x81:
1248                 val = insn_get(s, ot);
1249                 break;
1250             case 0x83:
1251                 val = (int8_t)insn_get(s, OT_BYTE);
1252                 break;
1253             }
1254
1255             gen_opi(s, op, ot, opreg, val);
1256             if (op != 7 && mod != 3) {
1257                 gen_op_st_T0_A0[ot]();
1258             }
1259         }
1260         break;
1261
1262         /**************************/
1263         /* inc, dec, and other misc arith */
1264     case 0x40 ... 0x47: /* inc Gv */
1265         ot = dflag ? OT_LONG : OT_WORD;
1266         gen_inc(s, ot, OR_EAX + (b & 7), 1);
1267         break;
1268     case 0x48 ... 0x4f: /* dec Gv */
1269         ot = dflag ? OT_LONG : OT_WORD;
1270         gen_inc(s, ot, OR_EAX + (b & 7), -1);
1271         break;
1272     case 0xf6: /* GRP3 */
1273     case 0xf7:
1274         if ((b & 1) == 0)
1275             ot = OT_BYTE;
1276         else
1277             ot = dflag ? OT_LONG : OT_WORD;
1278
1279         modrm = ldub(s->pc++);
1280         mod = (modrm >> 6) & 3;
1281         rm = modrm & 7;
1282         op = (modrm >> 3) & 7;
1283         if (mod != 3) {
1284             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1285             gen_op_ld_T0_A0[ot]();
1286         } else {
1287             gen_op_mov_TN_reg[ot][0][rm]();
1288         }
1289
1290         switch(op) {
1291         case 0: /* test */
1292             val = insn_get(s, ot);
1293             gen_op_movl_T1_im(val);
1294             gen_op_testl_T0_T1_cc();
1295             s->cc_op = CC_OP_LOGICB + ot;
1296             break;
1297         case 2: /* not */
1298             gen_op_notl_T0();
1299             if (mod != 3) {
1300                 gen_op_st_T0_A0[ot]();
1301             } else {
1302                 gen_op_mov_reg_T0[ot][rm]();
1303             }
1304             break;
1305         case 3: /* neg */
1306             gen_op_negl_T0_cc();
1307             if (mod != 3) {
1308                 gen_op_st_T0_A0[ot]();
1309             } else {
1310                 gen_op_mov_reg_T0[ot][rm]();
1311             }
1312             s->cc_op = CC_OP_SUBB + ot;
1313             break;
1314         case 4: /* mul */
1315             switch(ot) {
1316             case OT_BYTE:
1317                 gen_op_mulb_AL_T0();
1318                 break;
1319             case OT_WORD:
1320                 gen_op_mulw_AX_T0();
1321                 break;
1322             default:
1323             case OT_LONG:
1324                 gen_op_mull_EAX_T0();
1325                 break;
1326             }
1327             s->cc_op = CC_OP_MUL;
1328             break;
1329         case 5: /* imul */
1330             switch(ot) {
1331             case OT_BYTE:
1332                 gen_op_imulb_AL_T0();
1333                 break;
1334             case OT_WORD:
1335                 gen_op_imulw_AX_T0();
1336                 break;
1337             default:
1338             case OT_LONG:
1339                 gen_op_imull_EAX_T0();
1340                 break;
1341             }
1342             s->cc_op = CC_OP_MUL;
1343             break;
1344         case 6: /* div */
1345             switch(ot) {
1346             case OT_BYTE:
1347                 gen_op_divb_AL_T0();
1348                 break;
1349             case OT_WORD:
1350                 gen_op_divw_AX_T0();
1351                 break;
1352             default:
1353             case OT_LONG:
1354                 gen_op_divl_EAX_T0();
1355                 break;
1356             }
1357             break;
1358         case 7: /* idiv */
1359             switch(ot) {
1360             case OT_BYTE:
1361                 gen_op_idivb_AL_T0();
1362                 break;
1363             case OT_WORD:
1364                 gen_op_idivw_AX_T0();
1365                 break;
1366             default:
1367             case OT_LONG:
1368                 gen_op_idivl_EAX_T0();
1369                 break;
1370             }
1371             break;
1372         default:
1373             error("GRP3: bad instruction");
1374             return -1;
1375         }
1376         break;
1377
1378     case 0xfe: /* GRP4 */
1379     case 0xff: /* GRP5 */
1380         if ((b & 1) == 0)
1381             ot = OT_BYTE;
1382         else
1383             ot = dflag ? OT_LONG : OT_WORD;
1384
1385         modrm = ldub(s->pc++);
1386         mod = (modrm >> 6) & 3;
1387         rm = modrm & 7;
1388         op = (modrm >> 3) & 7;
1389         if (op >= 2 && b == 0xfe) {
1390             error("GRP4: bad instruction");
1391             return -1;
1392         }
1393         if (mod != 3) {
1394             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1395             gen_op_ld_T0_A0[ot]();
1396         } else {
1397             gen_op_mov_TN_reg[ot][0][rm]();
1398         }
1399
1400         switch(op) {
1401         case 0: /* inc Ev */
1402             gen_inc(s, ot, OR_TMP0, 1);
1403             if (mod != 3)
1404                 gen_op_st_T0_A0[ot]();
1405             else
1406                 gen_op_mov_reg_T0[ot][rm]();
1407             break;
1408         case 1: /* dec Ev */
1409             gen_inc(s, ot, OR_TMP0, -1);
1410             if (mod != 3)
1411                 gen_op_st_T0_A0[ot]();
1412             else
1413                 gen_op_mov_reg_T0[ot][rm]();
1414             break;
1415         case 2: /* call Ev */
1416             gen_op_movl_T1_im((long)s->pc);
1417             gen_op_pushl_T1();
1418             gen_op_jmp_T0();
1419             *is_jmp_ptr = 1;
1420             break;
1421         case 4: /* jmp Ev */
1422             gen_op_jmp_T0();
1423             *is_jmp_ptr = 1;
1424             break;
1425         case 6: /* push Ev */
1426             gen_op_pushl_T0();
1427             break;
1428         default:
1429             error("GRP5: bad instruction");
1430             return -1;
1431         }
1432         break;
1433
1434     case 0x84: /* test Ev, Gv */
1435     case 0x85: 
1436         if ((b & 1) == 0)
1437             ot = OT_BYTE;
1438         else
1439             ot = dflag ? OT_LONG : OT_WORD;
1440
1441         modrm = ldub(s->pc++);
1442         mod = (modrm >> 6) & 3;
1443         rm = modrm & 7;
1444         reg = (modrm >> 3) & 7;
1445         
1446         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1447         gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1448         gen_op_testl_T0_T1_cc();
1449         s->cc_op = CC_OP_LOGICB + ot;
1450         break;
1451         
1452     case 0xa8: /* test eAX, Iv */
1453     case 0xa9:
1454         if ((b & 1) == 0)
1455             ot = OT_BYTE;
1456         else
1457             ot = dflag ? OT_LONG : OT_WORD;
1458         val = insn_get(s, ot);
1459
1460         gen_op_mov_TN_reg[ot][0][OR_EAX]();
1461         gen_op_movl_T1_im(val);
1462         gen_op_testl_T0_T1_cc();
1463         s->cc_op = CC_OP_LOGICB + ot;
1464         break;
1465         
1466     case 0x98: /* CWDE/CBW */
1467         if (dflag)
1468             gen_op_movswl_EAX_AX();
1469         else
1470             gen_op_movsbw_AX_AL();
1471         break;
1472     case 0x99: /* CDQ/CWD */
1473         if (dflag)
1474             gen_op_movslq_EDX_EAX();
1475         else
1476             gen_op_movswl_DX_AX();
1477         break;
1478     case 0x1af: /* imul Gv, Ev */
1479     case 0x69: /* imul Gv, Ev, I */
1480     case 0x6b:
1481         ot = dflag ? OT_LONG : OT_WORD;
1482         modrm = ldub(s->pc++);
1483         reg = ((modrm >> 3) & 7) + OR_EAX;
1484         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1485         if (b == 0x69) {
1486             val = insn_get(s, ot);
1487             gen_op_movl_T1_im(val);
1488         } else if (b == 0x6b) {
1489             val = insn_get(s, OT_BYTE);
1490             gen_op_movl_T1_im(val);
1491         } else {
1492             gen_op_mov_TN_reg[ot][1][reg]();
1493         }
1494
1495         if (ot == OT_LONG) {
1496             gen_op_imull_T0_T1();
1497         } else {
1498             gen_op_imulw_T0_T1();
1499         }
1500         gen_op_mov_reg_T0[ot][reg]();
1501         s->cc_op = CC_OP_MUL;
1502         break;
1503         
1504         /**************************/
1505         /* push/pop */
1506     case 0x50 ... 0x57: /* push */
1507         gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1508         gen_op_pushl_T0();
1509         break;
1510     case 0x58 ... 0x5f: /* pop */
1511         gen_op_popl_T0();
1512         gen_op_mov_reg_T0[OT_LONG][b & 7]();
1513         break;
1514     case 0x68: /* push Iv */
1515     case 0x6a:
1516         ot = dflag ? OT_LONG : OT_WORD;
1517         if (b == 0x68)
1518             val = insn_get(s, ot);
1519         else
1520             val = (int8_t)insn_get(s, OT_BYTE);
1521         gen_op_movl_T0_im(val);
1522         gen_op_pushl_T0();
1523         break;
1524     case 0x8f: /* pop Ev */
1525         ot = dflag ? OT_LONG : OT_WORD;
1526         modrm = ldub(s->pc++);
1527         gen_op_popl_T0();
1528         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1529         break;
1530     case 0xc9: /* leave */
1531         gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1532         gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1533         gen_op_popl_T0();
1534         gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1535         break;
1536         /**************************/
1537         /* mov */
1538     case 0x88:
1539     case 0x89: /* mov Gv, Ev */
1540         if ((b & 1) == 0)
1541             ot = OT_BYTE;
1542         else
1543             ot = dflag ? OT_LONG : OT_WORD;
1544         modrm = ldub(s->pc++);
1545         reg = (modrm >> 3) & 7;
1546         
1547         /* generate a generic store */
1548         gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1549         break;
1550     case 0xc6:
1551     case 0xc7: /* mov Ev, Iv */
1552         if ((b & 1) == 0)
1553             ot = OT_BYTE;
1554         else
1555             ot = dflag ? OT_LONG : OT_WORD;
1556         modrm = ldub(s->pc++);
1557         mod = (modrm >> 6) & 3;
1558         if (mod != 3)
1559             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1560         val = insn_get(s, ot);
1561         gen_op_movl_T0_im(val);
1562         if (mod != 3)
1563             gen_op_st_T0_A0[ot]();
1564         else
1565             gen_op_mov_reg_T0[ot][modrm & 7]();
1566         break;
1567     case 0x8a:
1568     case 0x8b: /* mov Ev, Gv */
1569         if ((b & 1) == 0)
1570             ot = OT_BYTE;
1571         else
1572             ot = dflag ? OT_LONG : OT_WORD;
1573         modrm = ldub(s->pc++);
1574         reg = (modrm >> 3) & 7;
1575         
1576         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1577         gen_op_mov_reg_T0[ot][reg]();
1578         break;
1579
1580     case 0x1b6: /* movzbS Gv, Eb */
1581     case 0x1b7: /* movzwS Gv, Eb */
1582     case 0x1be: /* movsbS Gv, Eb */
1583     case 0x1bf: /* movswS Gv, Eb */
1584         {
1585             int d_ot;
1586             /* d_ot is the size of destination */
1587             d_ot = dflag + OT_WORD;
1588             /* ot is the size of source */
1589             ot = (b & 1) + OT_BYTE;
1590             modrm = ldub(s->pc++);
1591             reg = ((modrm >> 3) & 7) + OR_EAX;
1592             mod = (modrm >> 6) & 3;
1593             rm = modrm & 7;
1594             
1595             if (mod == 3) {
1596                 gen_op_mov_TN_reg[ot][0][rm]();
1597                 switch(ot | (b & 8)) {
1598                 case OT_BYTE:
1599                     gen_op_movzbl_T0_T0();
1600                     break;
1601                 case OT_BYTE | 8:
1602                     gen_op_movsbl_T0_T0();
1603                     break;
1604                 case OT_WORD:
1605                     gen_op_movzwl_T0_T0();
1606                     break;
1607                 default:
1608                 case OT_WORD | 8:
1609                     gen_op_movswl_T0_T0();
1610                     break;
1611                 }
1612                 gen_op_mov_reg_T0[d_ot][reg]();
1613             } else {
1614                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1615                 if (b & 8) {
1616                     gen_op_lds_T0_A0[ot]();
1617                 } else {
1618                     gen_op_ldu_T0_A0[ot]();
1619                 }
1620                 gen_op_mov_reg_T0[d_ot][reg]();
1621             }
1622         }
1623         break;
1624
1625     case 0x8d: /* lea */
1626         ot = dflag ? OT_LONG : OT_WORD;
1627         modrm = ldub(s->pc++);
1628         reg = (modrm >> 3) & 7;
1629
1630         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1631         gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1632         break;
1633         
1634     case 0xa0: /* mov EAX, Ov */
1635     case 0xa1:
1636     case 0xa2: /* mov Ov, EAX */
1637     case 0xa3:
1638         if ((b & 1) == 0)
1639             ot = OT_BYTE;
1640         else
1641             ot = dflag ? OT_LONG : OT_WORD;
1642         if (s->aflag)
1643             offset_addr = insn_get(s, OT_LONG);
1644         else
1645             offset_addr = insn_get(s, OT_WORD);
1646         gen_op_movl_A0_im(offset_addr);
1647         if ((b & 2) == 0) {
1648             gen_op_ld_T0_A0[ot]();
1649             gen_op_mov_reg_T0[ot][R_EAX]();
1650         } else {
1651             gen_op_mov_TN_reg[ot][0][R_EAX]();
1652             gen_op_st_T0_A0[ot]();
1653         }
1654         break;
1655
1656     case 0xb0 ... 0xb7: /* mov R, Ib */
1657         val = insn_get(s, OT_BYTE);
1658         gen_op_movl_T0_im(val);
1659         gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1660         break;
1661     case 0xb8 ... 0xbf: /* mov R, Iv */
1662         ot = dflag ? OT_LONG : OT_WORD;
1663         val = insn_get(s, ot);
1664         reg = OR_EAX + (b & 7);
1665         gen_op_movl_T0_im(val);
1666         gen_op_mov_reg_T0[ot][reg]();
1667         break;
1668
1669     case 0x91 ... 0x97: /* xchg R, EAX */
1670         ot = dflag ? OT_LONG : OT_WORD;
1671         reg = b & 7;
1672         gen_op_mov_TN_reg[ot][0][reg]();
1673         gen_op_mov_TN_reg[ot][1][R_EAX]();
1674         gen_op_mov_reg_T0[ot][R_EAX]();
1675         gen_op_mov_reg_T1[ot][reg]();
1676         break;
1677     case 0x86:
1678     case 0x87: /* xchg Ev, Gv */
1679         if ((b & 1) == 0)
1680             ot = OT_BYTE;
1681         else
1682             ot = dflag ? OT_LONG : OT_WORD;
1683         modrm = ldub(s->pc++);
1684         reg = (modrm >> 3) & 7;
1685
1686         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1687         gen_op_mov_TN_reg[ot][0][reg]();
1688         gen_op_ld_T1_A0[ot]();
1689         gen_op_st_T0_A0[ot]();
1690         gen_op_mov_reg_T1[ot][reg]();
1691         break;
1692         
1693         /************************/
1694         /* shifts */
1695     case 0xc0:
1696     case 0xc1:
1697         /* shift Ev,Ib */
1698         shift = 2;
1699     grp2:
1700         {
1701             if ((b & 1) == 0)
1702                 ot = OT_BYTE;
1703             else
1704                 ot = dflag ? OT_LONG : OT_WORD;
1705             
1706             modrm = ldub(s->pc++);
1707             mod = (modrm >> 6) & 3;
1708             rm = modrm & 7;
1709             op = (modrm >> 3) & 7;
1710             
1711             if (mod != 3) {
1712                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1713                 gen_op_ld_T0_A0[ot]();
1714                 opreg = OR_TMP0;
1715             } else {
1716                 opreg = rm + OR_EAX;
1717             }
1718
1719             /* simpler op */
1720             if (shift == 0) {
1721                 gen_shift(s, op, ot, opreg, OR_ECX);
1722             } else {
1723                 if (shift == 2) {
1724                     shift = ldub(s->pc++);
1725                 }
1726                 gen_shifti(s, op, ot, opreg, shift);
1727             }
1728
1729             if (mod != 3) {
1730                 gen_op_st_T0_A0[ot]();
1731             }
1732         }
1733         break;
1734     case 0xd0:
1735     case 0xd1:
1736         /* shift Ev,1 */
1737         shift = 1;
1738         goto grp2;
1739     case 0xd2:
1740     case 0xd3:
1741         /* shift Ev,cl */
1742         shift = 0;
1743         goto grp2;
1744
1745     case 0x1a4: /* shld imm */
1746         op = 0;
1747         shift = 1;
1748         goto do_shiftd;
1749     case 0x1a5: /* shld cl */
1750         op = 0;
1751         shift = 0;
1752         goto do_shiftd;
1753     case 0x1ac: /* shrd imm */
1754         op = 1;
1755         shift = 1;
1756         goto do_shiftd;
1757     case 0x1ad: /* shrd cl */
1758         op = 1;
1759         shift = 0;
1760     do_shiftd:
1761         ot = dflag ? OT_LONG : OT_WORD;
1762         modrm = ldub(s->pc++);
1763         mod = (modrm >> 6) & 3;
1764         rm = modrm & 7;
1765         reg = (modrm >> 3) & 7;
1766         
1767         if (mod != 3) {
1768             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1769             gen_op_ld_T0_A0[ot]();
1770         } else {
1771             gen_op_mov_TN_reg[ot][0][rm]();
1772         }
1773         gen_op_mov_TN_reg[ot][1][reg]();
1774         
1775         if (shift) {
1776             val = ldub(s->pc++);
1777             val &= 0x1f;
1778             if (val) {
1779                 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1780                 if (op == 0 && ot != OT_WORD)
1781                     s->cc_op = CC_OP_SHLB + ot;
1782                 else
1783                     s->cc_op = CC_OP_SARB + ot;
1784             }
1785         } else {
1786             if (s->cc_op != CC_OP_DYNAMIC)
1787                 gen_op_set_cc_op(s->cc_op);
1788             gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1789             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1790         }
1791         if (mod != 3) {
1792             gen_op_st_T0_A0[ot]();
1793         } else {
1794             gen_op_mov_reg_T0[ot][rm]();
1795         }
1796         break;
1797
1798         /************************/
1799         /* floats */
1800     case 0xd8 ... 0xdf: 
1801         modrm = ldub(s->pc++);
1802         mod = (modrm >> 6) & 3;
1803         rm = modrm & 7;
1804         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1805         
1806         if (mod != 3) {
1807             /* memory op */
1808             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1809             switch(op) {
1810             case 0x00 ... 0x07: /* fxxxs */
1811             case 0x10 ... 0x17: /* fixxxl */
1812             case 0x20 ... 0x27: /* fxxxl */
1813             case 0x30 ... 0x37: /* fixxx */
1814                 {
1815                     int op1;
1816                     op1 = op & 7;
1817
1818                     switch(op >> 4) {
1819                     case 0:
1820                         gen_op_flds_FT0_A0();
1821                         break;
1822                     case 1:
1823                         gen_op_fildl_FT0_A0();
1824                         break;
1825                     case 2:
1826                         gen_op_fldl_FT0_A0();
1827                         break;
1828                     case 3:
1829                     default:
1830                         gen_op_fild_FT0_A0();
1831                         break;
1832                     }
1833                     
1834                     gen_op_fp_arith_ST0_FT0[op1]();
1835                     if (op1 == 3) {
1836                         /* fcomp needs pop */
1837                         gen_op_fpop();
1838                     }
1839                 }
1840                 break;
1841             case 0x08: /* flds */
1842             case 0x0a: /* fsts */
1843             case 0x0b: /* fstps */
1844             case 0x18: /* fildl */
1845             case 0x1a: /* fistl */
1846             case 0x1b: /* fistpl */
1847             case 0x28: /* fldl */
1848             case 0x2a: /* fstl */
1849             case 0x2b: /* fstpl */
1850             case 0x38: /* filds */
1851             case 0x3a: /* fists */
1852             case 0x3b: /* fistps */
1853                 
1854                 switch(op & 7) {
1855                 case 0:
1856                     gen_op_fpush();
1857                     switch(op >> 4) {
1858                     case 0:
1859                         gen_op_flds_ST0_A0();
1860                         break;
1861                     case 1:
1862                         gen_op_fildl_ST0_A0();
1863                         break;
1864                     case 2:
1865                         gen_op_fldl_ST0_A0();
1866                         break;
1867                     case 3:
1868                     default:
1869                         gen_op_fild_ST0_A0();
1870                         break;
1871                     }
1872                     break;
1873                 default:
1874                     switch(op >> 4) {
1875                     case 0:
1876                         gen_op_fsts_ST0_A0();
1877                         break;
1878                     case 1:
1879                         gen_op_fistl_ST0_A0();
1880                         break;
1881                     case 2:
1882                         gen_op_fstl_ST0_A0();
1883                         break;
1884                     case 3:
1885                     default:
1886                         gen_op_fist_ST0_A0();
1887                         break;
1888                     }
1889                     if ((op & 7) == 3)
1890                         gen_op_fpop();
1891                     break;
1892                 }
1893                 break;
1894             case 0x0d: /* fldcw mem */
1895                 gen_op_fldcw_A0();
1896                 break;
1897             case 0x0f: /* fnstcw mem */
1898                 gen_op_fnstcw_A0();
1899                 break;
1900             case 0x1d: /* fldt mem */
1901                 gen_op_fpush();
1902                 gen_op_fldt_ST0_A0();
1903                 break;
1904             case 0x1f: /* fstpt mem */
1905                 gen_op_fstt_ST0_A0();
1906                 gen_op_fpop();
1907                 break;
1908             case 0x2f: /* fnstsw mem */
1909                 gen_op_fnstsw_A0();
1910                 break;
1911             case 0x3c: /* fbld */
1912                 gen_op_fpush();
1913                 gen_op_fbld_ST0_A0();
1914                 break;
1915             case 0x3e: /* fbstp */
1916                 gen_op_fbst_ST0_A0();
1917                 gen_op_fpop();
1918                 break;
1919             case 0x3d: /* fildll */
1920                 gen_op_fpush();
1921                 gen_op_fildll_ST0_A0();
1922                 break;
1923             case 0x3f: /* fistpll */
1924                 gen_op_fistll_ST0_A0();
1925                 gen_op_fpop();
1926                 break;
1927             default:
1928                 error("unhandled FPm [op=0x%02x]\n", op);
1929                 return -1;
1930             }
1931         } else {
1932             /* register float ops */
1933             opreg = rm;
1934
1935             switch(op) {
1936             case 0x08: /* fld sti */
1937                 gen_op_fpush();
1938                 gen_op_fmov_ST0_STN((opreg + 1) & 7);
1939                 break;
1940             case 0x09: /* fxchg sti */
1941                 gen_op_fxchg_ST0_STN(opreg);
1942                 break;
1943             case 0x0a: /* grp d9/2 */
1944                 switch(rm) {
1945                 case 0: /* fnop */
1946                     break;
1947                 default:
1948                     error("unhandled FP GRP d9/2\n");
1949                     return -1;
1950                 }
1951                 break;
1952             case 0x0c: /* grp d9/4 */
1953                 switch(rm) {
1954                 case 0: /* fchs */
1955                     gen_op_fchs_ST0();
1956                     break;
1957                 case 1: /* fabs */
1958                     gen_op_fabs_ST0();
1959                     break;
1960                 case 4: /* ftst */
1961                     gen_op_fldz_FT0();
1962                     gen_op_fcom_ST0_FT0();
1963                     break;
1964                 case 5: /* fxam */
1965                     gen_op_fxam_ST0();
1966                     break;
1967                 default:
1968                     return -1;
1969                 }
1970                 break;
1971             case 0x0d: /* grp d9/5 */
1972                 {
1973                     switch(rm) {
1974                     case 0:
1975                         gen_op_fpush();
1976                         gen_op_fld1_ST0();
1977                         break;
1978                     case 1:
1979                         gen_op_fpush();
1980                         gen_op_fldl2t_ST0();
1981                         break;
1982                     case 2:
1983                         gen_op_fpush();
1984                         gen_op_fldl2e_ST0();
1985                         break;
1986                     case 3:
1987                         gen_op_fpush();
1988                         gen_op_fldpi_ST0();
1989                         break;
1990                     case 4:
1991                         gen_op_fpush();
1992                         gen_op_fldlg2_ST0();
1993                         break;
1994                     case 5:
1995                         gen_op_fpush();
1996                         gen_op_fldln2_ST0();
1997                         break;
1998                     case 6:
1999                         gen_op_fpush();
2000                         gen_op_fldz_ST0();
2001                         break;
2002                     default:
2003                         return -1;
2004                     }
2005                 }
2006                 break;
2007             case 0x0e: /* grp d9/6 */
2008                 switch(rm) {
2009                 case 0: /* f2xm1 */
2010                     gen_op_f2xm1();
2011                     break;
2012                 case 1: /* fyl2x */
2013                     gen_op_fyl2x();
2014                     break;
2015                 case 2: /* fptan */
2016                     gen_op_fptan();
2017                     break;
2018                 case 3: /* fpatan */
2019                     gen_op_fpatan();
2020                     break;
2021                 case 4: /* fxtract */
2022                     gen_op_fxtract();
2023                     break;
2024                 case 5: /* fprem1 */
2025                     gen_op_fprem1();
2026                     break;
2027                 case 6: /* fdecstp */
2028                     gen_op_fdecstp();
2029                     break;
2030                 default:
2031                 case 7: /* fincstp */
2032                     gen_op_fincstp();
2033                     break;
2034                 }
2035                 break;
2036             case 0x0f: /* grp d9/7 */
2037                 switch(rm) {
2038                 case 0: /* fprem */
2039                     gen_op_fprem();
2040                     break;
2041                 case 1: /* fyl2xp1 */
2042                     gen_op_fyl2xp1();
2043                     break;
2044                 case 2: /* fsqrt */
2045                     gen_op_fsqrt();
2046                     break;
2047                 case 3: /* fsincos */
2048                     gen_op_fsincos();
2049                     break;
2050                 case 5: /* fscale */
2051                     gen_op_fscale();
2052                     break;
2053                 case 4: /* frndint */
2054                     gen_op_frndint();
2055                     break;
2056                 case 6: /* fsin */
2057                     gen_op_fsin();
2058                     break;
2059                 default:
2060                 case 7: /* fcos */
2061                     gen_op_fcos();
2062                     break;
2063                 }
2064                 break;
2065             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2066             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2067             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2068                 {
2069                     int op1;
2070                     
2071                     op1 = op & 7;
2072                     if (op >= 0x20) {
2073                         gen_op_fp_arith_STN_ST0[op1](opreg);
2074                         if (op >= 0x30)
2075                             gen_op_fpop();
2076                     } else {
2077                         gen_op_fmov_FT0_STN(opreg);
2078                         gen_op_fp_arith_ST0_FT0[op1]();
2079                     }
2080                 }
2081                 break;
2082             case 0x02: /* fcom */
2083                 gen_op_fmov_FT0_STN(opreg);
2084                 gen_op_fcom_ST0_FT0();
2085                 break;
2086             case 0x03: /* fcomp */
2087                 gen_op_fmov_FT0_STN(opreg);
2088                 gen_op_fcom_ST0_FT0();
2089                 gen_op_fpop();
2090                 break;
2091             case 0x15: /* da/5 */
2092                 switch(rm) {
2093                 case 1: /* fucompp */
2094                     gen_op_fmov_FT0_STN(1);
2095                     gen_op_fucom_ST0_FT0();
2096                     gen_op_fpop();
2097                     gen_op_fpop();
2098                     break;
2099                 default:
2100                     return -1;
2101                 }
2102                 break;
2103             case 0x2a: /* fst sti */
2104                 gen_op_fmov_STN_ST0(opreg);
2105                 break;
2106             case 0x2b: /* fstp sti */
2107                 gen_op_fmov_STN_ST0(opreg);
2108                 gen_op_fpop();
2109                 break;
2110             case 0x2c: /* fucom st(i) */
2111                 gen_op_fmov_FT0_STN(opreg);
2112                 gen_op_fucom_ST0_FT0();
2113                 break;
2114             case 0x2d: /* fucomp st(i) */
2115                 gen_op_fmov_FT0_STN(opreg);
2116                 gen_op_fucom_ST0_FT0();
2117                 gen_op_fpop();
2118                 break;
2119             case 0x33: /* de/3 */
2120                 switch(rm) {
2121                 case 1: /* fcompp */
2122                     gen_op_fmov_FT0_STN(1);
2123                     gen_op_fcom_ST0_FT0();
2124                     gen_op_fpop();
2125                     gen_op_fpop();
2126                     break;
2127                 default:
2128                     return -1;
2129                 }
2130                 break;
2131             case 0x3c: /* df/4 */
2132                 switch(rm) {
2133                 case 0:
2134                     gen_op_fnstsw_EAX();
2135                     break;
2136                 default:
2137                     error("unhandled FP %x df/4\n", rm);
2138                     return -1;
2139                 }
2140                 break;
2141             default:
2142                 error("unhandled FPr [op=0x%x]\n", op);
2143                 return -1;
2144             }
2145         }
2146         break;
2147         /************************/
2148         /* string ops */
2149     case 0xa4: /* movsS */
2150     case 0xa5:
2151         if ((b & 1) == 0)
2152             ot = OT_BYTE;
2153         else
2154             ot = dflag ? OT_LONG : OT_WORD;
2155         if (prefixes & PREFIX_REPZ) {
2156             gen_op_movs[3 + ot]();
2157         } else {
2158             gen_op_movs[ot]();
2159         }
2160         break;
2161         
2162     case 0xaa: /* stosS */
2163     case 0xab:
2164         if ((b & 1) == 0)
2165             ot = OT_BYTE;
2166         else
2167             ot = dflag ? OT_LONG : OT_WORD;
2168         if (prefixes & PREFIX_REPZ) {
2169             gen_op_stos[3 + ot]();
2170         } else {
2171             gen_op_stos[ot]();
2172         }
2173         break;
2174     case 0xac: /* lodsS */
2175     case 0xad:
2176         if ((b & 1) == 0)
2177             ot = OT_BYTE;
2178         else
2179             ot = dflag ? OT_LONG : OT_WORD;
2180         if (prefixes & PREFIX_REPZ) {
2181             gen_op_lods[3 + ot]();
2182         } else {
2183             gen_op_lods[ot]();
2184         }
2185         break;
2186     case 0xae: /* scasS */
2187     case 0xaf:
2188         if ((b & 1) == 0)
2189             ot = OT_BYTE;
2190         else
2191             ot = dflag ? OT_LONG : OT_WORD;
2192         if (prefixes & PREFIX_REPNZ) {
2193             if (s->cc_op != CC_OP_DYNAMIC)
2194                 gen_op_set_cc_op(s->cc_op);
2195             gen_op_scas[6 + ot]();
2196             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2197         } else if (prefixes & PREFIX_REPZ) {
2198             if (s->cc_op != CC_OP_DYNAMIC)
2199                 gen_op_set_cc_op(s->cc_op);
2200             gen_op_scas[3 + ot]();
2201             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2202         } else {
2203             gen_op_scas[ot]();
2204             s->cc_op = CC_OP_SUBB + ot;
2205         }
2206         break;
2207
2208     case 0xa6: /* cmpsS */
2209     case 0xa7:
2210         if ((b & 1) == 0)
2211             ot = OT_BYTE;
2212         else
2213             ot = dflag ? OT_LONG : OT_WORD;
2214         if (prefixes & PREFIX_REPNZ) {
2215             if (s->cc_op != CC_OP_DYNAMIC)
2216                 gen_op_set_cc_op(s->cc_op);
2217             gen_op_cmps[6 + ot]();
2218             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2219         } else if (prefixes & PREFIX_REPZ) {
2220             if (s->cc_op != CC_OP_DYNAMIC)
2221                 gen_op_set_cc_op(s->cc_op);
2222             gen_op_cmps[3 + ot]();
2223             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2224         } else {
2225             gen_op_cmps[ot]();
2226             s->cc_op = CC_OP_SUBB + ot;
2227         }
2228         break;
2229         
2230         /************************/
2231         /* port I/O */
2232     case 0x6c: /* insS */
2233     case 0x6d:
2234         if ((b & 1) == 0)
2235             ot = OT_BYTE;
2236         else
2237             ot = dflag ? OT_LONG : OT_WORD;
2238         if (prefixes & PREFIX_REPZ) {
2239             gen_op_ins[3 + ot]();
2240         } else {
2241             gen_op_ins[ot]();
2242         }
2243         break;
2244     case 0x6e: /* outsS */
2245     case 0x6f:
2246         if ((b & 1) == 0)
2247             ot = OT_BYTE;
2248         else
2249             ot = dflag ? OT_LONG : OT_WORD;
2250         if (prefixes & PREFIX_REPZ) {
2251             gen_op_outs[3 + ot]();
2252         } else {
2253             gen_op_outs[ot]();
2254         }
2255         break;
2256     case 0xe4:
2257     case 0xe5:
2258         if ((b & 1) == 0)
2259             ot = OT_BYTE;
2260         else
2261             ot = dflag ? OT_LONG : OT_WORD;
2262         val = ldub(s->pc++);
2263         gen_op_movl_T0_im(val);
2264         gen_op_in[ot]();
2265         gen_op_mov_reg_T1[ot][R_EAX]();
2266         break;
2267     case 0xe6:
2268     case 0xe7:
2269         if ((b & 1) == 0)
2270             ot = OT_BYTE;
2271         else
2272             ot = dflag ? OT_LONG : OT_WORD;
2273         val = ldub(s->pc++);
2274         gen_op_movl_T0_im(val);
2275         gen_op_mov_TN_reg[ot][1][R_EAX]();
2276         gen_op_out[ot]();
2277         break;
2278     case 0xec:
2279     case 0xed:
2280         if ((b & 1) == 0)
2281             ot = OT_BYTE;
2282         else
2283             ot = dflag ? OT_LONG : OT_WORD;
2284         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2285         gen_op_in[ot]();
2286         gen_op_mov_reg_T1[ot][R_EAX]();
2287         break;
2288     case 0xee:
2289     case 0xef:
2290         if ((b & 1) == 0)
2291             ot = OT_BYTE;
2292         else
2293             ot = dflag ? OT_LONG : OT_WORD;
2294         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2295         gen_op_mov_TN_reg[ot][1][R_EAX]();
2296         gen_op_out[ot]();
2297         break;
2298
2299         /************************/
2300         /* control */
2301     case 0xc2: /* ret im */
2302         /* XXX: handle stack pop ? */
2303         val = ldsw(s->pc);
2304         s->pc += 2;
2305         gen_op_popl_T0();
2306         gen_op_addl_ESP_im(val);
2307         gen_op_jmp_T0();
2308         *is_jmp_ptr = 1;
2309         break;
2310     case 0xc3: /* ret */
2311         gen_op_popl_T0();
2312         gen_op_jmp_T0();
2313         *is_jmp_ptr = 1;
2314         break;
2315     case 0xe8: /* call */
2316         val = insn_get(s, OT_LONG);
2317         val += (long)s->pc;
2318         gen_op_movl_T1_im((long)s->pc);
2319         gen_op_pushl_T1();
2320         gen_op_jmp_im(val);
2321         *is_jmp_ptr = 1;
2322         break;
2323     case 0xe9: /* jmp */
2324         val = insn_get(s, OT_LONG);
2325         val += (long)s->pc;
2326         gen_op_jmp_im(val);
2327         *is_jmp_ptr = 1;
2328         break;
2329     case 0xeb: /* jmp Jb */
2330         val = (int8_t)insn_get(s, OT_BYTE);
2331         val += (long)s->pc;
2332         gen_op_jmp_im(val);
2333         *is_jmp_ptr = 1;
2334         break;
2335     case 0x70 ... 0x7f: /* jcc Jb */
2336         val = (int8_t)insn_get(s, OT_BYTE);
2337         val += (long)s->pc;
2338         goto do_jcc;
2339     case 0x180 ... 0x18f: /* jcc Jv */
2340         if (dflag) {
2341             val = insn_get(s, OT_LONG);
2342         } else {
2343             val = (int16_t)insn_get(s, OT_WORD); 
2344         }
2345         val += (long)s->pc; /* XXX: fix 16 bit wrap */
2346     do_jcc:
2347         gen_jcc(s, b, val);
2348         *is_jmp_ptr = 1;
2349         break;
2350
2351     case 0x190 ... 0x19f:
2352         modrm = ldub(s->pc++);
2353         gen_setcc(s, b);
2354         gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2355         break;
2356
2357         /************************/
2358         /* flags */
2359     case 0x9c: /* pushf */
2360         if (s->cc_op != CC_OP_DYNAMIC)
2361             gen_op_set_cc_op(s->cc_op);
2362         gen_op_movl_T0_eflags();
2363         gen_op_pushl_T0();
2364         break;
2365     case 0x9d: /* popf */
2366         gen_op_popl_T0();
2367         gen_op_movl_eflags_T0();
2368         s->cc_op = CC_OP_EFLAGS;
2369         break;
2370     case 0x9e: /* sahf */
2371         gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2372         if (s->cc_op != CC_OP_DYNAMIC)
2373             gen_op_set_cc_op(s->cc_op);
2374         gen_op_movb_eflags_T0();
2375         s->cc_op = CC_OP_EFLAGS;
2376         break;
2377     case 0x9f: /* lahf */
2378         if (s->cc_op != CC_OP_DYNAMIC)
2379             gen_op_set_cc_op(s->cc_op);
2380         gen_op_movl_T0_eflags();
2381         gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2382         break;
2383     case 0xf5: /* cmc */
2384         if (s->cc_op != CC_OP_DYNAMIC)
2385             gen_op_set_cc_op(s->cc_op);
2386         gen_op_cmc();
2387         s->cc_op = CC_OP_EFLAGS;
2388         break;
2389     case 0xf8: /* clc */
2390         if (s->cc_op != CC_OP_DYNAMIC)
2391             gen_op_set_cc_op(s->cc_op);
2392         gen_op_clc();
2393         s->cc_op = CC_OP_EFLAGS;
2394         break;
2395     case 0xf9: /* stc */
2396         if (s->cc_op != CC_OP_DYNAMIC)
2397             gen_op_set_cc_op(s->cc_op);
2398         gen_op_stc();
2399         s->cc_op = CC_OP_EFLAGS;
2400         break;
2401     case 0xfc: /* cld */
2402         gen_op_cld();
2403         break;
2404     case 0xfd: /* std */
2405         gen_op_std();
2406         break;
2407
2408         /************************/
2409         /* bit operations */
2410     case 0x1ba: /* bt/bts/btr/btc Gv, im */
2411         ot = dflag ? OT_LONG : OT_WORD;
2412         modrm = ldub(s->pc++);
2413         op = (modrm >> 3) & 7;
2414         mod = (modrm >> 6) & 3;
2415         rm = modrm & 7;
2416         if (mod != 3) {
2417             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2418             gen_op_ld_T0_A0[ot]();
2419         } else {
2420             gen_op_mov_TN_reg[ot][0][rm]();
2421         }
2422         /* load shift */
2423         val = ldub(s->pc++);
2424         gen_op_movl_T1_im(val);
2425         if (op < 4)
2426             return -1;
2427         op -= 4;
2428         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2429         s->cc_op = CC_OP_SARB + ot;
2430         if (op != 0) {
2431             if (mod != 3)
2432                 gen_op_st_T0_A0[ot]();
2433             else
2434                 gen_op_mov_reg_T0[ot][rm]();
2435         }
2436         break;
2437     case 0x1a3: /* bt Gv, Ev */
2438         op = 0;
2439         goto do_btx;
2440     case 0x1ab: /* bts */
2441         op = 1;
2442         goto do_btx;
2443     case 0x1b3: /* btr */
2444         op = 2;
2445         goto do_btx;
2446     case 0x1bb: /* btc */
2447         op = 3;
2448     do_btx:
2449         ot = dflag ? OT_LONG : OT_WORD;
2450         modrm = ldub(s->pc++);
2451         reg = (modrm >> 3) & 7;
2452         mod = (modrm >> 6) & 3;
2453         rm = modrm & 7;
2454         gen_op_mov_TN_reg[OT_LONG][1][reg]();
2455         if (mod != 3) {
2456             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2457             /* specific case: we need to add a displacement */
2458             if (ot == OT_WORD)
2459                 gen_op_add_bitw_A0_T1();
2460             else
2461                 gen_op_add_bitl_A0_T1();
2462             gen_op_ld_T0_A0[ot]();
2463         } else {
2464             gen_op_mov_TN_reg[ot][0][rm]();
2465         }
2466         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2467         s->cc_op = CC_OP_SARB + ot;
2468         if (op != 0) {
2469             if (mod != 3)
2470                 gen_op_st_T0_A0[ot]();
2471             else
2472                 gen_op_mov_reg_T0[ot][rm]();
2473         }
2474         break;
2475     case 0x1bc: /* bsf */
2476     case 0x1bd: /* bsr */
2477         ot = dflag ? OT_LONG : OT_WORD;
2478         modrm = ldub(s->pc++);
2479         reg = (modrm >> 3) & 7;
2480         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2481         gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2482         /* NOTE: we always write back the result. Intel doc says it is
2483            undefined if T0 == 0 */
2484         gen_op_mov_reg_T0[ot][reg]();
2485         s->cc_op = CC_OP_LOGICB + ot;
2486         break;
2487         /************************/
2488         /* misc */
2489     case 0x90: /* nop */
2490         break;
2491     case 0xcc: /* int3 */
2492         gen_op_int3((long)pc_start);
2493         *is_jmp_ptr = 1;
2494         break;
2495     case 0xcd: /* int N */
2496         val = ldub(s->pc++);
2497         /* XXX: currently we ignore the interrupt number */
2498         gen_op_int_im((long)pc_start);
2499         *is_jmp_ptr = 1;
2500         break;
2501     case 0xce: /* into */
2502         if (s->cc_op != CC_OP_DYNAMIC)
2503             gen_op_set_cc_op(s->cc_op);
2504         gen_op_into((long)pc_start, (long)s->pc);
2505         *is_jmp_ptr = 1;
2506         break;
2507     case 0x1c8 ... 0x1cf: /* bswap reg */
2508       reg = b & 7;
2509       gen_op_mov_TN_reg[OT_LONG][0][reg]();
2510       gen_op_bswapl_T0();
2511       gen_op_mov_reg_T0[OT_LONG][reg]();
2512       break;
2513       
2514 #if 0
2515     case 0x1a2: /* cpuid */
2516         gen_insn0(OP_ASM);
2517         break;
2518 #endif
2519     default:
2520         error("unknown opcode %x", b);
2521         return -1;
2522     }
2523     return (long)s->pc;
2524 }
2525
2526 /* return the next pc */
2527 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
2528                      int *gen_code_size_ptr, uint8_t *pc_start)
2529 {
2530     DisasContext dc1, *dc = &dc1;
2531     uint8_t *gen_code_end, *pc_ptr;
2532     int is_jmp;
2533     long ret;
2534 #ifdef DEBUG_DISAS
2535     struct disassemble_info disasm_info;
2536 #endif
2537
2538     dc->cc_op = CC_OP_DYNAMIC;
2539     gen_code_ptr = gen_code_buf;
2540     gen_code_end = gen_code_buf + max_code_size - 4096;
2541     gen_start();
2542
2543     is_jmp = 0;
2544     pc_ptr = pc_start;
2545     do {
2546         ret = disas_insn(dc, pc_ptr, &is_jmp);
2547         if (ret == -1) 
2548             error("unknown instruction at PC=0x%x B=%02x %02x", 
2549                   pc_ptr, pc_ptr[0], pc_ptr[1]);
2550         pc_ptr = (void *)ret;
2551     } while (!is_jmp && gen_code_ptr < gen_code_end);
2552     /* we must store the eflags state if it is not already done */
2553     if (dc->cc_op != CC_OP_DYNAMIC)
2554         gen_op_set_cc_op(dc->cc_op);
2555     if (!is_jmp) {
2556         /* we add an additionnal jmp to update the simulated PC */
2557         gen_op_jmp_im(ret);
2558     }
2559     gen_end();
2560     *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2561
2562 #ifdef DEBUG_DISAS
2563     if (loglevel) {
2564         uint8_t *pc;
2565         int count;
2566
2567         INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2568 #if 0        
2569         disasm_info.flavour = bfd_get_flavour (abfd);
2570         disasm_info.arch = bfd_get_arch (abfd);
2571         disasm_info.mach = bfd_get_mach (abfd);
2572 #endif
2573 #ifdef WORDS_BIGENDIAN
2574         disasm_info.endian = BFD_ENDIAN_BIG;
2575 #else
2576         disasm_info.endian = BFD_ENDIAN_LITTLE;
2577 #endif        
2578         fprintf(logfile, "IN:\n");
2579         disasm_info.buffer = pc_start;
2580         disasm_info.buffer_vma = (unsigned long)pc_start;
2581         disasm_info.buffer_length = pc_ptr - pc_start;
2582         pc = pc_start;
2583         while (pc < pc_ptr) {
2584             fprintf(logfile, "0x%08lx:  ", (long)pc);
2585             count = print_insn_i386((unsigned long)pc, &disasm_info);
2586             fprintf(logfile, "\n");
2587             pc += count;
2588         }
2589         fprintf(logfile, "\n");
2590         
2591         pc = gen_code_buf;
2592         disasm_info.buffer = pc;
2593         disasm_info.buffer_vma = (unsigned long)pc;
2594         disasm_info.buffer_length = *gen_code_size_ptr;
2595         fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2596         while (pc < gen_code_ptr) {
2597             fprintf(logfile, "0x%08lx:  ", (long)pc);
2598             count = print_insn_i386((unsigned long)pc, &disasm_info);
2599             fprintf(logfile, "\n");
2600             pc += count;
2601         }
2602         fprintf(logfile, "\n");
2603     }
2604 #endif
2605     return 0;
2606 }
2607
2608 CPUX86State *cpu_x86_init(void)
2609 {
2610     CPUX86State *env;
2611     int i;
2612
2613     cpu_x86_tblocks_init();
2614
2615     env = malloc(sizeof(CPUX86State));
2616     if (!env)
2617         return NULL;
2618     memset(env, 0, sizeof(CPUX86State));
2619     /* basic FPU init */
2620     for(i = 0;i < 8; i++)
2621         env->fptags[i] = 1;
2622     env->fpuc = 0x37f;
2623     /* flags setup */
2624     env->cc_op = CC_OP_EFLAGS;
2625     env->df = 1;
2626     return env;
2627 }
2628
2629 void cpu_x86_close(CPUX86State *env)
2630 {
2631     free(env);
2632 }