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