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