added pusha/popa/rdtsc/bcd ops
[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 0x60: /* pusha */
1515         if (s->dflag)
1516             gen_op_pushal();
1517         else
1518             gen_op_pushaw();
1519         break;
1520     case 0x61: /* popa */
1521         if (s->dflag)
1522             gen_op_popal();
1523         else
1524             gen_op_popaw();
1525         break;
1526     case 0x68: /* push Iv */
1527     case 0x6a:
1528         ot = dflag ? OT_LONG : OT_WORD;
1529         if (b == 0x68)
1530             val = insn_get(s, ot);
1531         else
1532             val = (int8_t)insn_get(s, OT_BYTE);
1533         gen_op_movl_T0_im(val);
1534         gen_op_pushl_T0();
1535         break;
1536     case 0x8f: /* pop Ev */
1537         ot = dflag ? OT_LONG : OT_WORD;
1538         modrm = ldub(s->pc++);
1539         gen_op_popl_T0();
1540         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1541         break;
1542     case 0xc8: /* enter */
1543         {
1544             int level;
1545             val = lduw(s->pc);
1546             s->pc += 2;
1547             level = ldub(s->pc++);
1548             level &= 0x1f;
1549             gen_op_enterl(val, level);
1550         }
1551         break;
1552     case 0xc9: /* leave */
1553         gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1554         gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1555         gen_op_popl_T0();
1556         gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1557         break;
1558         /**************************/
1559         /* mov */
1560     case 0x88:
1561     case 0x89: /* mov Gv, Ev */
1562         if ((b & 1) == 0)
1563             ot = OT_BYTE;
1564         else
1565             ot = dflag ? OT_LONG : OT_WORD;
1566         modrm = ldub(s->pc++);
1567         reg = (modrm >> 3) & 7;
1568         
1569         /* generate a generic store */
1570         gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1571         break;
1572     case 0xc6:
1573     case 0xc7: /* mov Ev, Iv */
1574         if ((b & 1) == 0)
1575             ot = OT_BYTE;
1576         else
1577             ot = dflag ? OT_LONG : OT_WORD;
1578         modrm = ldub(s->pc++);
1579         mod = (modrm >> 6) & 3;
1580         if (mod != 3)
1581             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1582         val = insn_get(s, ot);
1583         gen_op_movl_T0_im(val);
1584         if (mod != 3)
1585             gen_op_st_T0_A0[ot]();
1586         else
1587             gen_op_mov_reg_T0[ot][modrm & 7]();
1588         break;
1589     case 0x8a:
1590     case 0x8b: /* mov Ev, Gv */
1591         if ((b & 1) == 0)
1592             ot = OT_BYTE;
1593         else
1594             ot = dflag ? OT_LONG : OT_WORD;
1595         modrm = ldub(s->pc++);
1596         reg = (modrm >> 3) & 7;
1597         
1598         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1599         gen_op_mov_reg_T0[ot][reg]();
1600         break;
1601
1602     case 0x1b6: /* movzbS Gv, Eb */
1603     case 0x1b7: /* movzwS Gv, Eb */
1604     case 0x1be: /* movsbS Gv, Eb */
1605     case 0x1bf: /* movswS Gv, Eb */
1606         {
1607             int d_ot;
1608             /* d_ot is the size of destination */
1609             d_ot = dflag + OT_WORD;
1610             /* ot is the size of source */
1611             ot = (b & 1) + OT_BYTE;
1612             modrm = ldub(s->pc++);
1613             reg = ((modrm >> 3) & 7) + OR_EAX;
1614             mod = (modrm >> 6) & 3;
1615             rm = modrm & 7;
1616             
1617             if (mod == 3) {
1618                 gen_op_mov_TN_reg[ot][0][rm]();
1619                 switch(ot | (b & 8)) {
1620                 case OT_BYTE:
1621                     gen_op_movzbl_T0_T0();
1622                     break;
1623                 case OT_BYTE | 8:
1624                     gen_op_movsbl_T0_T0();
1625                     break;
1626                 case OT_WORD:
1627                     gen_op_movzwl_T0_T0();
1628                     break;
1629                 default:
1630                 case OT_WORD | 8:
1631                     gen_op_movswl_T0_T0();
1632                     break;
1633                 }
1634                 gen_op_mov_reg_T0[d_ot][reg]();
1635             } else {
1636                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1637                 if (b & 8) {
1638                     gen_op_lds_T0_A0[ot]();
1639                 } else {
1640                     gen_op_ldu_T0_A0[ot]();
1641                 }
1642                 gen_op_mov_reg_T0[d_ot][reg]();
1643             }
1644         }
1645         break;
1646
1647     case 0x8d: /* lea */
1648         ot = dflag ? OT_LONG : OT_WORD;
1649         modrm = ldub(s->pc++);
1650         reg = (modrm >> 3) & 7;
1651
1652         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1653         gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1654         break;
1655         
1656     case 0xa0: /* mov EAX, Ov */
1657     case 0xa1:
1658     case 0xa2: /* mov Ov, EAX */
1659     case 0xa3:
1660         if ((b & 1) == 0)
1661             ot = OT_BYTE;
1662         else
1663             ot = dflag ? OT_LONG : OT_WORD;
1664         if (s->aflag)
1665             offset_addr = insn_get(s, OT_LONG);
1666         else
1667             offset_addr = insn_get(s, OT_WORD);
1668         gen_op_movl_A0_im(offset_addr);
1669         if ((b & 2) == 0) {
1670             gen_op_ld_T0_A0[ot]();
1671             gen_op_mov_reg_T0[ot][R_EAX]();
1672         } else {
1673             gen_op_mov_TN_reg[ot][0][R_EAX]();
1674             gen_op_st_T0_A0[ot]();
1675         }
1676         break;
1677
1678     case 0xb0 ... 0xb7: /* mov R, Ib */
1679         val = insn_get(s, OT_BYTE);
1680         gen_op_movl_T0_im(val);
1681         gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1682         break;
1683     case 0xb8 ... 0xbf: /* mov R, Iv */
1684         ot = dflag ? OT_LONG : OT_WORD;
1685         val = insn_get(s, ot);
1686         reg = OR_EAX + (b & 7);
1687         gen_op_movl_T0_im(val);
1688         gen_op_mov_reg_T0[ot][reg]();
1689         break;
1690
1691     case 0x91 ... 0x97: /* xchg R, EAX */
1692         ot = dflag ? OT_LONG : OT_WORD;
1693         reg = b & 7;
1694         gen_op_mov_TN_reg[ot][0][reg]();
1695         gen_op_mov_TN_reg[ot][1][R_EAX]();
1696         gen_op_mov_reg_T0[ot][R_EAX]();
1697         gen_op_mov_reg_T1[ot][reg]();
1698         break;
1699     case 0x86:
1700     case 0x87: /* xchg Ev, Gv */
1701         if ((b & 1) == 0)
1702             ot = OT_BYTE;
1703         else
1704             ot = dflag ? OT_LONG : OT_WORD;
1705         modrm = ldub(s->pc++);
1706         reg = (modrm >> 3) & 7;
1707
1708         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1709         gen_op_mov_TN_reg[ot][0][reg]();
1710         gen_op_ld_T1_A0[ot]();
1711         gen_op_st_T0_A0[ot]();
1712         gen_op_mov_reg_T1[ot][reg]();
1713         break;
1714         
1715         /************************/
1716         /* shifts */
1717     case 0xc0:
1718     case 0xc1:
1719         /* shift Ev,Ib */
1720         shift = 2;
1721     grp2:
1722         {
1723             if ((b & 1) == 0)
1724                 ot = OT_BYTE;
1725             else
1726                 ot = dflag ? OT_LONG : OT_WORD;
1727             
1728             modrm = ldub(s->pc++);
1729             mod = (modrm >> 6) & 3;
1730             rm = modrm & 7;
1731             op = (modrm >> 3) & 7;
1732             
1733             if (mod != 3) {
1734                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1735                 gen_op_ld_T0_A0[ot]();
1736                 opreg = OR_TMP0;
1737             } else {
1738                 opreg = rm + OR_EAX;
1739             }
1740
1741             /* simpler op */
1742             if (shift == 0) {
1743                 gen_shift(s, op, ot, opreg, OR_ECX);
1744             } else {
1745                 if (shift == 2) {
1746                     shift = ldub(s->pc++);
1747                 }
1748                 gen_shifti(s, op, ot, opreg, shift);
1749             }
1750
1751             if (mod != 3) {
1752                 gen_op_st_T0_A0[ot]();
1753             }
1754         }
1755         break;
1756     case 0xd0:
1757     case 0xd1:
1758         /* shift Ev,1 */
1759         shift = 1;
1760         goto grp2;
1761     case 0xd2:
1762     case 0xd3:
1763         /* shift Ev,cl */
1764         shift = 0;
1765         goto grp2;
1766
1767     case 0x1a4: /* shld imm */
1768         op = 0;
1769         shift = 1;
1770         goto do_shiftd;
1771     case 0x1a5: /* shld cl */
1772         op = 0;
1773         shift = 0;
1774         goto do_shiftd;
1775     case 0x1ac: /* shrd imm */
1776         op = 1;
1777         shift = 1;
1778         goto do_shiftd;
1779     case 0x1ad: /* shrd cl */
1780         op = 1;
1781         shift = 0;
1782     do_shiftd:
1783         ot = dflag ? OT_LONG : OT_WORD;
1784         modrm = ldub(s->pc++);
1785         mod = (modrm >> 6) & 3;
1786         rm = modrm & 7;
1787         reg = (modrm >> 3) & 7;
1788         
1789         if (mod != 3) {
1790             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1791             gen_op_ld_T0_A0[ot]();
1792         } else {
1793             gen_op_mov_TN_reg[ot][0][rm]();
1794         }
1795         gen_op_mov_TN_reg[ot][1][reg]();
1796         
1797         if (shift) {
1798             val = ldub(s->pc++);
1799             val &= 0x1f;
1800             if (val) {
1801                 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1802                 if (op == 0 && ot != OT_WORD)
1803                     s->cc_op = CC_OP_SHLB + ot;
1804                 else
1805                     s->cc_op = CC_OP_SARB + ot;
1806             }
1807         } else {
1808             if (s->cc_op != CC_OP_DYNAMIC)
1809                 gen_op_set_cc_op(s->cc_op);
1810             gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1811             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1812         }
1813         if (mod != 3) {
1814             gen_op_st_T0_A0[ot]();
1815         } else {
1816             gen_op_mov_reg_T0[ot][rm]();
1817         }
1818         break;
1819
1820         /************************/
1821         /* floats */
1822     case 0xd8 ... 0xdf: 
1823         modrm = ldub(s->pc++);
1824         mod = (modrm >> 6) & 3;
1825         rm = modrm & 7;
1826         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1827         
1828         if (mod != 3) {
1829             /* memory op */
1830             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1831             switch(op) {
1832             case 0x00 ... 0x07: /* fxxxs */
1833             case 0x10 ... 0x17: /* fixxxl */
1834             case 0x20 ... 0x27: /* fxxxl */
1835             case 0x30 ... 0x37: /* fixxx */
1836                 {
1837                     int op1;
1838                     op1 = op & 7;
1839
1840                     switch(op >> 4) {
1841                     case 0:
1842                         gen_op_flds_FT0_A0();
1843                         break;
1844                     case 1:
1845                         gen_op_fildl_FT0_A0();
1846                         break;
1847                     case 2:
1848                         gen_op_fldl_FT0_A0();
1849                         break;
1850                     case 3:
1851                     default:
1852                         gen_op_fild_FT0_A0();
1853                         break;
1854                     }
1855                     
1856                     gen_op_fp_arith_ST0_FT0[op1]();
1857                     if (op1 == 3) {
1858                         /* fcomp needs pop */
1859                         gen_op_fpop();
1860                     }
1861                 }
1862                 break;
1863             case 0x08: /* flds */
1864             case 0x0a: /* fsts */
1865             case 0x0b: /* fstps */
1866             case 0x18: /* fildl */
1867             case 0x1a: /* fistl */
1868             case 0x1b: /* fistpl */
1869             case 0x28: /* fldl */
1870             case 0x2a: /* fstl */
1871             case 0x2b: /* fstpl */
1872             case 0x38: /* filds */
1873             case 0x3a: /* fists */
1874             case 0x3b: /* fistps */
1875                 
1876                 switch(op & 7) {
1877                 case 0:
1878                     gen_op_fpush();
1879                     switch(op >> 4) {
1880                     case 0:
1881                         gen_op_flds_ST0_A0();
1882                         break;
1883                     case 1:
1884                         gen_op_fildl_ST0_A0();
1885                         break;
1886                     case 2:
1887                         gen_op_fldl_ST0_A0();
1888                         break;
1889                     case 3:
1890                     default:
1891                         gen_op_fild_ST0_A0();
1892                         break;
1893                     }
1894                     break;
1895                 default:
1896                     switch(op >> 4) {
1897                     case 0:
1898                         gen_op_fsts_ST0_A0();
1899                         break;
1900                     case 1:
1901                         gen_op_fistl_ST0_A0();
1902                         break;
1903                     case 2:
1904                         gen_op_fstl_ST0_A0();
1905                         break;
1906                     case 3:
1907                     default:
1908                         gen_op_fist_ST0_A0();
1909                         break;
1910                     }
1911                     if ((op & 7) == 3)
1912                         gen_op_fpop();
1913                     break;
1914                 }
1915                 break;
1916             case 0x0d: /* fldcw mem */
1917                 gen_op_fldcw_A0();
1918                 break;
1919             case 0x0f: /* fnstcw mem */
1920                 gen_op_fnstcw_A0();
1921                 break;
1922             case 0x1d: /* fldt mem */
1923                 gen_op_fpush();
1924                 gen_op_fldt_ST0_A0();
1925                 break;
1926             case 0x1f: /* fstpt mem */
1927                 gen_op_fstt_ST0_A0();
1928                 gen_op_fpop();
1929                 break;
1930             case 0x2f: /* fnstsw mem */
1931                 gen_op_fnstsw_A0();
1932                 break;
1933             case 0x3c: /* fbld */
1934                 gen_op_fpush();
1935                 gen_op_fbld_ST0_A0();
1936                 break;
1937             case 0x3e: /* fbstp */
1938                 gen_op_fbst_ST0_A0();
1939                 gen_op_fpop();
1940                 break;
1941             case 0x3d: /* fildll */
1942                 gen_op_fpush();
1943                 gen_op_fildll_ST0_A0();
1944                 break;
1945             case 0x3f: /* fistpll */
1946                 gen_op_fistll_ST0_A0();
1947                 gen_op_fpop();
1948                 break;
1949             default:
1950                 error("unhandled FPm [op=0x%02x]\n", op);
1951                 return -1;
1952             }
1953         } else {
1954             /* register float ops */
1955             opreg = rm;
1956
1957             switch(op) {
1958             case 0x08: /* fld sti */
1959                 gen_op_fpush();
1960                 gen_op_fmov_ST0_STN((opreg + 1) & 7);
1961                 break;
1962             case 0x09: /* fxchg sti */
1963                 gen_op_fxchg_ST0_STN(opreg);
1964                 break;
1965             case 0x0a: /* grp d9/2 */
1966                 switch(rm) {
1967                 case 0: /* fnop */
1968                     break;
1969                 default:
1970                     error("unhandled FP GRP d9/2\n");
1971                     return -1;
1972                 }
1973                 break;
1974             case 0x0c: /* grp d9/4 */
1975                 switch(rm) {
1976                 case 0: /* fchs */
1977                     gen_op_fchs_ST0();
1978                     break;
1979                 case 1: /* fabs */
1980                     gen_op_fabs_ST0();
1981                     break;
1982                 case 4: /* ftst */
1983                     gen_op_fldz_FT0();
1984                     gen_op_fcom_ST0_FT0();
1985                     break;
1986                 case 5: /* fxam */
1987                     gen_op_fxam_ST0();
1988                     break;
1989                 default:
1990                     return -1;
1991                 }
1992                 break;
1993             case 0x0d: /* grp d9/5 */
1994                 {
1995                     switch(rm) {
1996                     case 0:
1997                         gen_op_fpush();
1998                         gen_op_fld1_ST0();
1999                         break;
2000                     case 1:
2001                         gen_op_fpush();
2002                         gen_op_fldl2t_ST0();
2003                         break;
2004                     case 2:
2005                         gen_op_fpush();
2006                         gen_op_fldl2e_ST0();
2007                         break;
2008                     case 3:
2009                         gen_op_fpush();
2010                         gen_op_fldpi_ST0();
2011                         break;
2012                     case 4:
2013                         gen_op_fpush();
2014                         gen_op_fldlg2_ST0();
2015                         break;
2016                     case 5:
2017                         gen_op_fpush();
2018                         gen_op_fldln2_ST0();
2019                         break;
2020                     case 6:
2021                         gen_op_fpush();
2022                         gen_op_fldz_ST0();
2023                         break;
2024                     default:
2025                         return -1;
2026                     }
2027                 }
2028                 break;
2029             case 0x0e: /* grp d9/6 */
2030                 switch(rm) {
2031                 case 0: /* f2xm1 */
2032                     gen_op_f2xm1();
2033                     break;
2034                 case 1: /* fyl2x */
2035                     gen_op_fyl2x();
2036                     break;
2037                 case 2: /* fptan */
2038                     gen_op_fptan();
2039                     break;
2040                 case 3: /* fpatan */
2041                     gen_op_fpatan();
2042                     break;
2043                 case 4: /* fxtract */
2044                     gen_op_fxtract();
2045                     break;
2046                 case 5: /* fprem1 */
2047                     gen_op_fprem1();
2048                     break;
2049                 case 6: /* fdecstp */
2050                     gen_op_fdecstp();
2051                     break;
2052                 default:
2053                 case 7: /* fincstp */
2054                     gen_op_fincstp();
2055                     break;
2056                 }
2057                 break;
2058             case 0x0f: /* grp d9/7 */
2059                 switch(rm) {
2060                 case 0: /* fprem */
2061                     gen_op_fprem();
2062                     break;
2063                 case 1: /* fyl2xp1 */
2064                     gen_op_fyl2xp1();
2065                     break;
2066                 case 2: /* fsqrt */
2067                     gen_op_fsqrt();
2068                     break;
2069                 case 3: /* fsincos */
2070                     gen_op_fsincos();
2071                     break;
2072                 case 5: /* fscale */
2073                     gen_op_fscale();
2074                     break;
2075                 case 4: /* frndint */
2076                     gen_op_frndint();
2077                     break;
2078                 case 6: /* fsin */
2079                     gen_op_fsin();
2080                     break;
2081                 default:
2082                 case 7: /* fcos */
2083                     gen_op_fcos();
2084                     break;
2085                 }
2086                 break;
2087             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2088             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2089             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2090                 {
2091                     int op1;
2092                     
2093                     op1 = op & 7;
2094                     if (op >= 0x20) {
2095                         gen_op_fp_arith_STN_ST0[op1](opreg);
2096                         if (op >= 0x30)
2097                             gen_op_fpop();
2098                     } else {
2099                         gen_op_fmov_FT0_STN(opreg);
2100                         gen_op_fp_arith_ST0_FT0[op1]();
2101                     }
2102                 }
2103                 break;
2104             case 0x02: /* fcom */
2105                 gen_op_fmov_FT0_STN(opreg);
2106                 gen_op_fcom_ST0_FT0();
2107                 break;
2108             case 0x03: /* fcomp */
2109                 gen_op_fmov_FT0_STN(opreg);
2110                 gen_op_fcom_ST0_FT0();
2111                 gen_op_fpop();
2112                 break;
2113             case 0x15: /* da/5 */
2114                 switch(rm) {
2115                 case 1: /* fucompp */
2116                     gen_op_fmov_FT0_STN(1);
2117                     gen_op_fucom_ST0_FT0();
2118                     gen_op_fpop();
2119                     gen_op_fpop();
2120                     break;
2121                 default:
2122                     return -1;
2123                 }
2124                 break;
2125             case 0x2a: /* fst sti */
2126                 gen_op_fmov_STN_ST0(opreg);
2127                 break;
2128             case 0x2b: /* fstp sti */
2129                 gen_op_fmov_STN_ST0(opreg);
2130                 gen_op_fpop();
2131                 break;
2132             case 0x2c: /* fucom st(i) */
2133                 gen_op_fmov_FT0_STN(opreg);
2134                 gen_op_fucom_ST0_FT0();
2135                 break;
2136             case 0x2d: /* fucomp st(i) */
2137                 gen_op_fmov_FT0_STN(opreg);
2138                 gen_op_fucom_ST0_FT0();
2139                 gen_op_fpop();
2140                 break;
2141             case 0x33: /* de/3 */
2142                 switch(rm) {
2143                 case 1: /* fcompp */
2144                     gen_op_fmov_FT0_STN(1);
2145                     gen_op_fcom_ST0_FT0();
2146                     gen_op_fpop();
2147                     gen_op_fpop();
2148                     break;
2149                 default:
2150                     return -1;
2151                 }
2152                 break;
2153             case 0x3c: /* df/4 */
2154                 switch(rm) {
2155                 case 0:
2156                     gen_op_fnstsw_EAX();
2157                     break;
2158                 default:
2159                     error("unhandled FP %x df/4\n", rm);
2160                     return -1;
2161                 }
2162                 break;
2163             default:
2164                 error("unhandled FPr [op=0x%x]\n", op);
2165                 return -1;
2166             }
2167         }
2168         break;
2169         /************************/
2170         /* string ops */
2171     case 0xa4: /* movsS */
2172     case 0xa5:
2173         if ((b & 1) == 0)
2174             ot = OT_BYTE;
2175         else
2176             ot = dflag ? OT_LONG : OT_WORD;
2177         if (prefixes & PREFIX_REPZ) {
2178             gen_op_movs[3 + ot]();
2179         } else {
2180             gen_op_movs[ot]();
2181         }
2182         break;
2183         
2184     case 0xaa: /* stosS */
2185     case 0xab:
2186         if ((b & 1) == 0)
2187             ot = OT_BYTE;
2188         else
2189             ot = dflag ? OT_LONG : OT_WORD;
2190         if (prefixes & PREFIX_REPZ) {
2191             gen_op_stos[3 + ot]();
2192         } else {
2193             gen_op_stos[ot]();
2194         }
2195         break;
2196     case 0xac: /* lodsS */
2197     case 0xad:
2198         if ((b & 1) == 0)
2199             ot = OT_BYTE;
2200         else
2201             ot = dflag ? OT_LONG : OT_WORD;
2202         if (prefixes & PREFIX_REPZ) {
2203             gen_op_lods[3 + ot]();
2204         } else {
2205             gen_op_lods[ot]();
2206         }
2207         break;
2208     case 0xae: /* scasS */
2209     case 0xaf:
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_scas[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_scas[3 + ot]();
2223             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2224         } else {
2225             gen_op_scas[ot]();
2226             s->cc_op = CC_OP_SUBB + ot;
2227         }
2228         break;
2229
2230     case 0xa6: /* cmpsS */
2231     case 0xa7:
2232         if ((b & 1) == 0)
2233             ot = OT_BYTE;
2234         else
2235             ot = dflag ? OT_LONG : OT_WORD;
2236         if (prefixes & PREFIX_REPNZ) {
2237             if (s->cc_op != CC_OP_DYNAMIC)
2238                 gen_op_set_cc_op(s->cc_op);
2239             gen_op_cmps[6 + ot]();
2240             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2241         } else if (prefixes & PREFIX_REPZ) {
2242             if (s->cc_op != CC_OP_DYNAMIC)
2243                 gen_op_set_cc_op(s->cc_op);
2244             gen_op_cmps[3 + ot]();
2245             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2246         } else {
2247             gen_op_cmps[ot]();
2248             s->cc_op = CC_OP_SUBB + ot;
2249         }
2250         break;
2251         
2252         /************************/
2253         /* port I/O */
2254     case 0x6c: /* insS */
2255     case 0x6d:
2256         if ((b & 1) == 0)
2257             ot = OT_BYTE;
2258         else
2259             ot = dflag ? OT_LONG : OT_WORD;
2260         if (prefixes & PREFIX_REPZ) {
2261             gen_op_ins[3 + ot]();
2262         } else {
2263             gen_op_ins[ot]();
2264         }
2265         break;
2266     case 0x6e: /* outsS */
2267     case 0x6f:
2268         if ((b & 1) == 0)
2269             ot = OT_BYTE;
2270         else
2271             ot = dflag ? OT_LONG : OT_WORD;
2272         if (prefixes & PREFIX_REPZ) {
2273             gen_op_outs[3 + ot]();
2274         } else {
2275             gen_op_outs[ot]();
2276         }
2277         break;
2278     case 0xe4:
2279     case 0xe5:
2280         if ((b & 1) == 0)
2281             ot = OT_BYTE;
2282         else
2283             ot = dflag ? OT_LONG : OT_WORD;
2284         val = ldub(s->pc++);
2285         gen_op_movl_T0_im(val);
2286         gen_op_in[ot]();
2287         gen_op_mov_reg_T1[ot][R_EAX]();
2288         break;
2289     case 0xe6:
2290     case 0xe7:
2291         if ((b & 1) == 0)
2292             ot = OT_BYTE;
2293         else
2294             ot = dflag ? OT_LONG : OT_WORD;
2295         val = ldub(s->pc++);
2296         gen_op_movl_T0_im(val);
2297         gen_op_mov_TN_reg[ot][1][R_EAX]();
2298         gen_op_out[ot]();
2299         break;
2300     case 0xec:
2301     case 0xed:
2302         if ((b & 1) == 0)
2303             ot = OT_BYTE;
2304         else
2305             ot = dflag ? OT_LONG : OT_WORD;
2306         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2307         gen_op_in[ot]();
2308         gen_op_mov_reg_T1[ot][R_EAX]();
2309         break;
2310     case 0xee:
2311     case 0xef:
2312         if ((b & 1) == 0)
2313             ot = OT_BYTE;
2314         else
2315             ot = dflag ? OT_LONG : OT_WORD;
2316         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2317         gen_op_mov_TN_reg[ot][1][R_EAX]();
2318         gen_op_out[ot]();
2319         break;
2320
2321         /************************/
2322         /* control */
2323     case 0xc2: /* ret im */
2324         /* XXX: handle stack pop ? */
2325         val = ldsw(s->pc);
2326         s->pc += 2;
2327         gen_op_popl_T0();
2328         gen_op_addl_ESP_im(val);
2329         gen_op_jmp_T0();
2330         *is_jmp_ptr = 1;
2331         break;
2332     case 0xc3: /* ret */
2333         gen_op_popl_T0();
2334         gen_op_jmp_T0();
2335         *is_jmp_ptr = 1;
2336         break;
2337     case 0xe8: /* call */
2338         val = insn_get(s, OT_LONG);
2339         val += (long)s->pc;
2340         gen_op_movl_T1_im((long)s->pc);
2341         gen_op_pushl_T1();
2342         gen_op_jmp_im(val);
2343         *is_jmp_ptr = 1;
2344         break;
2345     case 0xe9: /* jmp */
2346         val = insn_get(s, OT_LONG);
2347         val += (long)s->pc;
2348         gen_op_jmp_im(val);
2349         *is_jmp_ptr = 1;
2350         break;
2351     case 0xeb: /* jmp Jb */
2352         val = (int8_t)insn_get(s, OT_BYTE);
2353         val += (long)s->pc;
2354         gen_op_jmp_im(val);
2355         *is_jmp_ptr = 1;
2356         break;
2357     case 0x70 ... 0x7f: /* jcc Jb */
2358         val = (int8_t)insn_get(s, OT_BYTE);
2359         val += (long)s->pc;
2360         goto do_jcc;
2361     case 0x180 ... 0x18f: /* jcc Jv */
2362         if (dflag) {
2363             val = insn_get(s, OT_LONG);
2364         } else {
2365             val = (int16_t)insn_get(s, OT_WORD); 
2366         }
2367         val += (long)s->pc; /* XXX: fix 16 bit wrap */
2368     do_jcc:
2369         gen_jcc(s, b, val);
2370         *is_jmp_ptr = 1;
2371         break;
2372
2373     case 0x190 ... 0x19f:
2374         modrm = ldub(s->pc++);
2375         gen_setcc(s, b);
2376         gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2377         break;
2378
2379         /************************/
2380         /* flags */
2381     case 0x9c: /* pushf */
2382         if (s->cc_op != CC_OP_DYNAMIC)
2383             gen_op_set_cc_op(s->cc_op);
2384         gen_op_movl_T0_eflags();
2385         gen_op_pushl_T0();
2386         break;
2387     case 0x9d: /* popf */
2388         gen_op_popl_T0();
2389         gen_op_movl_eflags_T0();
2390         s->cc_op = CC_OP_EFLAGS;
2391         break;
2392     case 0x9e: /* sahf */
2393         gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2394         if (s->cc_op != CC_OP_DYNAMIC)
2395             gen_op_set_cc_op(s->cc_op);
2396         gen_op_movb_eflags_T0();
2397         s->cc_op = CC_OP_EFLAGS;
2398         break;
2399     case 0x9f: /* lahf */
2400         if (s->cc_op != CC_OP_DYNAMIC)
2401             gen_op_set_cc_op(s->cc_op);
2402         gen_op_movl_T0_eflags();
2403         gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2404         break;
2405     case 0xf5: /* cmc */
2406         if (s->cc_op != CC_OP_DYNAMIC)
2407             gen_op_set_cc_op(s->cc_op);
2408         gen_op_cmc();
2409         s->cc_op = CC_OP_EFLAGS;
2410         break;
2411     case 0xf8: /* clc */
2412         if (s->cc_op != CC_OP_DYNAMIC)
2413             gen_op_set_cc_op(s->cc_op);
2414         gen_op_clc();
2415         s->cc_op = CC_OP_EFLAGS;
2416         break;
2417     case 0xf9: /* stc */
2418         if (s->cc_op != CC_OP_DYNAMIC)
2419             gen_op_set_cc_op(s->cc_op);
2420         gen_op_stc();
2421         s->cc_op = CC_OP_EFLAGS;
2422         break;
2423     case 0xfc: /* cld */
2424         gen_op_cld();
2425         break;
2426     case 0xfd: /* std */
2427         gen_op_std();
2428         break;
2429
2430         /************************/
2431         /* bit operations */
2432     case 0x1ba: /* bt/bts/btr/btc Gv, im */
2433         ot = dflag ? OT_LONG : OT_WORD;
2434         modrm = ldub(s->pc++);
2435         op = (modrm >> 3) & 7;
2436         mod = (modrm >> 6) & 3;
2437         rm = modrm & 7;
2438         if (mod != 3) {
2439             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2440             gen_op_ld_T0_A0[ot]();
2441         } else {
2442             gen_op_mov_TN_reg[ot][0][rm]();
2443         }
2444         /* load shift */
2445         val = ldub(s->pc++);
2446         gen_op_movl_T1_im(val);
2447         if (op < 4)
2448             return -1;
2449         op -= 4;
2450         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2451         s->cc_op = CC_OP_SARB + ot;
2452         if (op != 0) {
2453             if (mod != 3)
2454                 gen_op_st_T0_A0[ot]();
2455             else
2456                 gen_op_mov_reg_T0[ot][rm]();
2457         }
2458         break;
2459     case 0x1a3: /* bt Gv, Ev */
2460         op = 0;
2461         goto do_btx;
2462     case 0x1ab: /* bts */
2463         op = 1;
2464         goto do_btx;
2465     case 0x1b3: /* btr */
2466         op = 2;
2467         goto do_btx;
2468     case 0x1bb: /* btc */
2469         op = 3;
2470     do_btx:
2471         ot = dflag ? OT_LONG : OT_WORD;
2472         modrm = ldub(s->pc++);
2473         reg = (modrm >> 3) & 7;
2474         mod = (modrm >> 6) & 3;
2475         rm = modrm & 7;
2476         gen_op_mov_TN_reg[OT_LONG][1][reg]();
2477         if (mod != 3) {
2478             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2479             /* specific case: we need to add a displacement */
2480             if (ot == OT_WORD)
2481                 gen_op_add_bitw_A0_T1();
2482             else
2483                 gen_op_add_bitl_A0_T1();
2484             gen_op_ld_T0_A0[ot]();
2485         } else {
2486             gen_op_mov_TN_reg[ot][0][rm]();
2487         }
2488         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2489         s->cc_op = CC_OP_SARB + ot;
2490         if (op != 0) {
2491             if (mod != 3)
2492                 gen_op_st_T0_A0[ot]();
2493             else
2494                 gen_op_mov_reg_T0[ot][rm]();
2495         }
2496         break;
2497     case 0x1bc: /* bsf */
2498     case 0x1bd: /* bsr */
2499         ot = dflag ? OT_LONG : OT_WORD;
2500         modrm = ldub(s->pc++);
2501         reg = (modrm >> 3) & 7;
2502         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2503         gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2504         /* NOTE: we always write back the result. Intel doc says it is
2505            undefined if T0 == 0 */
2506         gen_op_mov_reg_T0[ot][reg]();
2507         s->cc_op = CC_OP_LOGICB + ot;
2508         break;
2509         /************************/
2510         /* bcd */
2511     case 0x27: /* daa */
2512         if (s->cc_op != CC_OP_DYNAMIC)
2513             gen_op_set_cc_op(s->cc_op);
2514         gen_op_daa();
2515         s->cc_op = CC_OP_EFLAGS;
2516         break;
2517     case 0x2f: /* das */
2518         if (s->cc_op != CC_OP_DYNAMIC)
2519             gen_op_set_cc_op(s->cc_op);
2520         gen_op_das();
2521         s->cc_op = CC_OP_EFLAGS;
2522         break;
2523     case 0x37: /* aaa */
2524         if (s->cc_op != CC_OP_DYNAMIC)
2525             gen_op_set_cc_op(s->cc_op);
2526         gen_op_aaa();
2527         s->cc_op = CC_OP_EFLAGS;
2528         break;
2529     case 0x3f: /* aas */
2530         if (s->cc_op != CC_OP_DYNAMIC)
2531             gen_op_set_cc_op(s->cc_op);
2532         gen_op_aas();
2533         s->cc_op = CC_OP_EFLAGS;
2534         break;
2535     case 0xd4: /* aam */
2536         val = ldub(s->pc++);
2537         gen_op_aam(val);
2538         s->cc_op = CC_OP_LOGICB;
2539         break;
2540     case 0xd5: /* aad */
2541         val = ldub(s->pc++);
2542         gen_op_aad(val);
2543         s->cc_op = CC_OP_LOGICB;
2544         break;
2545         /************************/
2546         /* misc */
2547     case 0x90: /* nop */
2548         break;
2549     case 0xcc: /* int3 */
2550         gen_op_int3((long)pc_start);
2551         *is_jmp_ptr = 1;
2552         break;
2553     case 0xcd: /* int N */
2554         val = ldub(s->pc++);
2555         /* XXX: currently we ignore the interrupt number */
2556         gen_op_int_im((long)pc_start);
2557         *is_jmp_ptr = 1;
2558         break;
2559     case 0xce: /* into */
2560         if (s->cc_op != CC_OP_DYNAMIC)
2561             gen_op_set_cc_op(s->cc_op);
2562         gen_op_into((long)pc_start, (long)s->pc);
2563         *is_jmp_ptr = 1;
2564         break;
2565     case 0x1c8 ... 0x1cf: /* bswap reg */
2566         reg = b & 7;
2567         gen_op_mov_TN_reg[OT_LONG][0][reg]();
2568         gen_op_bswapl_T0();
2569         gen_op_mov_reg_T0[OT_LONG][reg]();
2570         break;
2571     case 0xd6: /* salc */
2572         if (s->cc_op != CC_OP_DYNAMIC)
2573             gen_op_set_cc_op(s->cc_op);
2574         gen_op_salc();
2575         break;
2576     case 0x1a2: /* rdtsc */
2577         gen_op_rdtsc();
2578         break;
2579 #if 0
2580     case 0x1a2: /* cpuid */
2581         gen_insn0(OP_ASM);
2582         break;
2583 #endif
2584     default:
2585         error("unknown opcode 0x%x", b);
2586         return -1;
2587     }
2588     return (long)s->pc;
2589 }
2590
2591 /* return the next pc */
2592 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
2593                      int *gen_code_size_ptr, uint8_t *pc_start)
2594 {
2595     DisasContext dc1, *dc = &dc1;
2596     uint8_t *gen_code_end, *pc_ptr;
2597     int is_jmp;
2598     long ret;
2599 #ifdef DEBUG_DISAS
2600     struct disassemble_info disasm_info;
2601 #endif
2602
2603     dc->cc_op = CC_OP_DYNAMIC;
2604     gen_code_ptr = gen_code_buf;
2605     gen_code_end = gen_code_buf + max_code_size - 4096;
2606     gen_start();
2607
2608     is_jmp = 0;
2609     pc_ptr = pc_start;
2610     do {
2611         ret = disas_insn(dc, pc_ptr, &is_jmp);
2612         if (ret == -1) 
2613             error("unknown instruction at PC=0x%x B=%02x %02x", 
2614                   pc_ptr, pc_ptr[0], pc_ptr[1]);
2615         pc_ptr = (void *)ret;
2616     } while (!is_jmp && gen_code_ptr < gen_code_end);
2617     /* we must store the eflags state if it is not already done */
2618     if (dc->cc_op != CC_OP_DYNAMIC)
2619         gen_op_set_cc_op(dc->cc_op);
2620     if (!is_jmp) {
2621         /* we add an additionnal jmp to update the simulated PC */
2622         gen_op_jmp_im(ret);
2623     }
2624     gen_end();
2625     *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2626
2627 #ifdef DEBUG_DISAS
2628     if (loglevel) {
2629         uint8_t *pc;
2630         int count;
2631
2632         INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2633 #if 0        
2634         disasm_info.flavour = bfd_get_flavour (abfd);
2635         disasm_info.arch = bfd_get_arch (abfd);
2636         disasm_info.mach = bfd_get_mach (abfd);
2637 #endif
2638 #ifdef WORDS_BIGENDIAN
2639         disasm_info.endian = BFD_ENDIAN_BIG;
2640 #else
2641         disasm_info.endian = BFD_ENDIAN_LITTLE;
2642 #endif        
2643         fprintf(logfile, "IN:\n");
2644         disasm_info.buffer = pc_start;
2645         disasm_info.buffer_vma = (unsigned long)pc_start;
2646         disasm_info.buffer_length = pc_ptr - pc_start;
2647         pc = pc_start;
2648         while (pc < pc_ptr) {
2649             fprintf(logfile, "0x%08lx:  ", (long)pc);
2650             count = print_insn_i386((unsigned long)pc, &disasm_info);
2651             fprintf(logfile, "\n");
2652             pc += count;
2653         }
2654         fprintf(logfile, "\n");
2655         
2656         pc = gen_code_buf;
2657         disasm_info.buffer = pc;
2658         disasm_info.buffer_vma = (unsigned long)pc;
2659         disasm_info.buffer_length = *gen_code_size_ptr;
2660         fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2661         while (pc < gen_code_ptr) {
2662             fprintf(logfile, "0x%08lx:  ", (long)pc);
2663             count = print_insn_i386((unsigned long)pc, &disasm_info);
2664             fprintf(logfile, "\n");
2665             pc += count;
2666         }
2667         fprintf(logfile, "\n");
2668     }
2669 #endif
2670     return 0;
2671 }
2672
2673 CPUX86State *cpu_x86_init(void)
2674 {
2675     CPUX86State *env;
2676     int i;
2677
2678     cpu_x86_tblocks_init();
2679
2680     env = malloc(sizeof(CPUX86State));
2681     if (!env)
2682         return NULL;
2683     memset(env, 0, sizeof(CPUX86State));
2684     /* basic FPU init */
2685     for(i = 0;i < 8; i++)
2686         env->fptags[i] = 1;
2687     env->fpuc = 0x37f;
2688     /* flags setup */
2689     env->cc_op = CC_OP_EFLAGS;
2690     env->df = 1;
2691     return env;
2692 }
2693
2694 void cpu_x86_close(CPUX86State *env)
2695 {
2696     free(env);
2697 }