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