Statistics
| Branch: | Revision:

root / translate-i386.c @ 586314f2

History | View | Annotate | Download (58.3 kB)

1
#include <stdarg.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <string.h>
5
#include <inttypes.h>
6
#include <assert.h>
7

    
8
#define DEBUG_DISAS
9

    
10
#define IN_OP_I386
11
#include "cpu-i386.h"
12

    
13
/* dump all code */
14
#ifdef DEBUG_DISAS
15
#include "dis-asm.h"
16
#endif
17

    
18
static uint8_t *gen_code_ptr;
19
int __op_param1, __op_param2, __op_param3;
20

    
21
extern FILE *logfile;
22
extern int loglevel;
23

    
24
/* supress that */
25
static void error(const char *fmt, ...)
26
{
27
    va_list ap;
28

    
29
    va_start(ap, fmt);
30
    vfprintf(stderr, fmt, ap);
31
    va_end(ap);
32
    exit(1);
33
}
34

    
35
#define PREFIX_REPZ 1
36
#define PREFIX_REPNZ 2
37
#define PREFIX_LOCK 4
38
#define PREFIX_CS 8
39
#define PREFIX_SS 0x10
40
#define PREFIX_DS 0x20
41
#define PREFIX_ES 0x40
42
#define PREFIX_FS 0x80
43
#define PREFIX_GS 0x100
44
#define PREFIX_DATA 0x200
45
#define PREFIX_ADR 0x400
46
#define PREFIX_FWAIT 0x800
47

    
48
typedef struct DisasContext {
49
    /* current insn context */
50
    int prefix;
51
    int aflag, dflag;
52
    uint8_t *pc; /* current pc */
53
    int cc_op; /* current CC operation */
54
    int f_st;
55
} DisasContext;
56

    
57
/* i386 arith/logic operations */
58
enum {
59
    OP_ADDL, 
60
    OP_ORL, 
61
    OP_ADCL, 
62
    OP_SBBL,
63
    OP_ANDL, 
64
    OP_SUBL, 
65
    OP_XORL, 
66
    OP_CMPL,
67
};
68

    
69
/* i386 shift ops */
70
enum {
71
    OP_ROL, 
72
    OP_ROR, 
73
    OP_RCL, 
74
    OP_RCR, 
75
    OP_SHL, 
76
    OP_SHR, 
77
    OP_SHL1, /* undocumented */
78
    OP_SAR = 7,
79
};
80

    
81
#include "op-i386.h"
82

    
83
/* operand size */
84
enum {
85
    OT_BYTE = 0,
86
    OT_WORD,
87
    OT_LONG, 
88
    OT_QUAD,
89
};
90

    
91
enum {
92
    /* I386 int registers */
93
    OR_EAX,   /* MUST be even numbered */
94
    OR_ECX,
95
    OR_EDX,
96
    OR_EBX,
97
    OR_ESP,
98
    OR_EBP,
99
    OR_ESI,
100
    OR_EDI,
101

    
102
    /* I386 float registers */
103
    OR_ST0,
104
    OR_ST1,
105
    OR_ST2,
106
    OR_ST3,
107
    OR_ST4,
108
    OR_ST5,
109
    OR_ST6,
110
    OR_ST7,
111
    OR_TMP0,    /* temporary operand register */
112
    OR_TMP1,
113
    OR_A0, /* temporary register used when doing address evaluation */
114
    OR_EFLAGS,  /* cpu flags */
115
    OR_ITMP0, /* used for byte/word insertion */
116
    OR_ITMP1, /* used for byte/word insertion */
117
    OR_ITMP2, /* used for byte/word insertion */
118
    OR_FTMP0, /* float temporary */
119
    OR_DF,    /* D flag, for string ops */
120
    OR_ZERO, /* fixed zero register */
121
    OR_IM, /* dummy immediate value register */
122
    NB_OREGS,
123
};
124

    
125
#if 0
126
static const double tab_const[7] = {
127
    1.0, 
128
    3.32192809488736234789, /* log2(10) */
129
    M_LOG2E,
130
    M_PI,
131
    0.30102999566398119521, /* log10(2) */
132
    M_LN2,
133
    0.0
134
};
135
#endif
136

    
137
typedef void (GenOpFunc)(void);
138
typedef void (GenOpFunc1)(long);
139
typedef void (GenOpFunc2)(long, long);
140
                    
141
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
142
    [OT_BYTE] = {
143
        gen_op_movb_EAX_T0,
144
        gen_op_movb_ECX_T0,
145
        gen_op_movb_EDX_T0,
146
        gen_op_movb_EBX_T0,
147
        gen_op_movh_EAX_T0,
148
        gen_op_movh_ECX_T0,
149
        gen_op_movh_EDX_T0,
150
        gen_op_movh_EBX_T0,
151
    },
152
    [OT_WORD] = {
153
        gen_op_movw_EAX_T0,
154
        gen_op_movw_ECX_T0,
155
        gen_op_movw_EDX_T0,
156
        gen_op_movw_EBX_T0,
157
        gen_op_movw_ESP_T0,
158
        gen_op_movw_EBP_T0,
159
        gen_op_movw_ESI_T0,
160
        gen_op_movw_EDI_T0,
161
    },
162
    [OT_LONG] = {
163
        gen_op_movl_EAX_T0,
164
        gen_op_movl_ECX_T0,
165
        gen_op_movl_EDX_T0,
166
        gen_op_movl_EBX_T0,
167
        gen_op_movl_ESP_T0,
168
        gen_op_movl_EBP_T0,
169
        gen_op_movl_ESI_T0,
170
        gen_op_movl_EDI_T0,
171
    },
172
};
173

    
174
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
175
    [OT_BYTE] = {
176
        gen_op_movb_EAX_T1,
177
        gen_op_movb_ECX_T1,
178
        gen_op_movb_EDX_T1,
179
        gen_op_movb_EBX_T1,
180
        gen_op_movh_EAX_T1,
181
        gen_op_movh_ECX_T1,
182
        gen_op_movh_EDX_T1,
183
        gen_op_movh_EBX_T1,
184
    },
185
    [OT_WORD] = {
186
        gen_op_movw_EAX_T1,
187
        gen_op_movw_ECX_T1,
188
        gen_op_movw_EDX_T1,
189
        gen_op_movw_EBX_T1,
190
        gen_op_movw_ESP_T1,
191
        gen_op_movw_EBP_T1,
192
        gen_op_movw_ESI_T1,
193
        gen_op_movw_EDI_T1,
194
    },
195
    [OT_LONG] = {
196
        gen_op_movl_EAX_T1,
197
        gen_op_movl_ECX_T1,
198
        gen_op_movl_EDX_T1,
199
        gen_op_movl_EBX_T1,
200
        gen_op_movl_ESP_T1,
201
        gen_op_movl_EBP_T1,
202
        gen_op_movl_ESI_T1,
203
        gen_op_movl_EDI_T1,
204
    },
205
};
206

    
207
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
208
    [0] = {
209
        gen_op_movw_EAX_A0,
210
        gen_op_movw_ECX_A0,
211
        gen_op_movw_EDX_A0,
212
        gen_op_movw_EBX_A0,
213
        gen_op_movw_ESP_A0,
214
        gen_op_movw_EBP_A0,
215
        gen_op_movw_ESI_A0,
216
        gen_op_movw_EDI_A0,
217
    },
218
    [1] = {
219
        gen_op_movl_EAX_A0,
220
        gen_op_movl_ECX_A0,
221
        gen_op_movl_EDX_A0,
222
        gen_op_movl_EBX_A0,
223
        gen_op_movl_ESP_A0,
224
        gen_op_movl_EBP_A0,
225
        gen_op_movl_ESI_A0,
226
        gen_op_movl_EDI_A0,
227
    },
228
};
229

    
230
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
231
{
232
    [OT_BYTE] = {
233
        {
234
            gen_op_movl_T0_EAX,
235
            gen_op_movl_T0_ECX,
236
            gen_op_movl_T0_EDX,
237
            gen_op_movl_T0_EBX,
238
            gen_op_movh_T0_EAX,
239
            gen_op_movh_T0_ECX,
240
            gen_op_movh_T0_EDX,
241
            gen_op_movh_T0_EBX,
242
        },
243
        {
244
            gen_op_movl_T1_EAX,
245
            gen_op_movl_T1_ECX,
246
            gen_op_movl_T1_EDX,
247
            gen_op_movl_T1_EBX,
248
            gen_op_movh_T1_EAX,
249
            gen_op_movh_T1_ECX,
250
            gen_op_movh_T1_EDX,
251
            gen_op_movh_T1_EBX,
252
        },
253
    },
254
    [OT_WORD] = {
255
        {
256
            gen_op_movl_T0_EAX,
257
            gen_op_movl_T0_ECX,
258
            gen_op_movl_T0_EDX,
259
            gen_op_movl_T0_EBX,
260
            gen_op_movl_T0_ESP,
261
            gen_op_movl_T0_EBP,
262
            gen_op_movl_T0_ESI,
263
            gen_op_movl_T0_EDI,
264
        },
265
        {
266
            gen_op_movl_T1_EAX,
267
            gen_op_movl_T1_ECX,
268
            gen_op_movl_T1_EDX,
269
            gen_op_movl_T1_EBX,
270
            gen_op_movl_T1_ESP,
271
            gen_op_movl_T1_EBP,
272
            gen_op_movl_T1_ESI,
273
            gen_op_movl_T1_EDI,
274
        },
275
    },
276
    [OT_LONG] = {
277
        {
278
            gen_op_movl_T0_EAX,
279
            gen_op_movl_T0_ECX,
280
            gen_op_movl_T0_EDX,
281
            gen_op_movl_T0_EBX,
282
            gen_op_movl_T0_ESP,
283
            gen_op_movl_T0_EBP,
284
            gen_op_movl_T0_ESI,
285
            gen_op_movl_T0_EDI,
286
        },
287
        {
288
            gen_op_movl_T1_EAX,
289
            gen_op_movl_T1_ECX,
290
            gen_op_movl_T1_EDX,
291
            gen_op_movl_T1_EBX,
292
            gen_op_movl_T1_ESP,
293
            gen_op_movl_T1_EBP,
294
            gen_op_movl_T1_ESI,
295
            gen_op_movl_T1_EDI,
296
        },
297
    },
298
};
299

    
300
static GenOpFunc *gen_op_movl_A0_reg[8] = {
301
    gen_op_movl_A0_EAX,
302
    gen_op_movl_A0_ECX,
303
    gen_op_movl_A0_EDX,
304
    gen_op_movl_A0_EBX,
305
    gen_op_movl_A0_ESP,
306
    gen_op_movl_A0_EBP,
307
    gen_op_movl_A0_ESI,
308
    gen_op_movl_A0_EDI,
309
};
310

    
311
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
312
    [0] = {
313
        gen_op_addl_A0_EAX,
314
        gen_op_addl_A0_ECX,
315
        gen_op_addl_A0_EDX,
316
        gen_op_addl_A0_EBX,
317
        gen_op_addl_A0_ESP,
318
        gen_op_addl_A0_EBP,
319
        gen_op_addl_A0_ESI,
320
        gen_op_addl_A0_EDI,
321
    },
322
    [1] = {
323
        gen_op_addl_A0_EAX_s1,
324
        gen_op_addl_A0_ECX_s1,
325
        gen_op_addl_A0_EDX_s1,
326
        gen_op_addl_A0_EBX_s1,
327
        gen_op_addl_A0_ESP_s1,
328
        gen_op_addl_A0_EBP_s1,
329
        gen_op_addl_A0_ESI_s1,
330
        gen_op_addl_A0_EDI_s1,
331
    },
332
    [2] = {
333
        gen_op_addl_A0_EAX_s2,
334
        gen_op_addl_A0_ECX_s2,
335
        gen_op_addl_A0_EDX_s2,
336
        gen_op_addl_A0_EBX_s2,
337
        gen_op_addl_A0_ESP_s2,
338
        gen_op_addl_A0_EBP_s2,
339
        gen_op_addl_A0_ESI_s2,
340
        gen_op_addl_A0_EDI_s2,
341
    },
342
    [3] = {
343
        gen_op_addl_A0_EAX_s3,
344
        gen_op_addl_A0_ECX_s3,
345
        gen_op_addl_A0_EDX_s3,
346
        gen_op_addl_A0_EBX_s3,
347
        gen_op_addl_A0_ESP_s3,
348
        gen_op_addl_A0_EBP_s3,
349
        gen_op_addl_A0_ESI_s3,
350
        gen_op_addl_A0_EDI_s3,
351
    },
352
};
353

    
354
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
355
    gen_op_addl_T0_T1_cc,
356
    gen_op_orl_T0_T1_cc,
357
    gen_op_adcl_T0_T1_cc,
358
    gen_op_sbbl_T0_T1_cc,
359
    gen_op_andl_T0_T1_cc,
360
    gen_op_subl_T0_T1_cc,
361
    gen_op_xorl_T0_T1_cc,
362
    gen_op_cmpl_T0_T1_cc,
363
};
364

    
365
static const int cc_op_arithb[8] = {
366
    CC_OP_ADDB,
367
    CC_OP_LOGICB,
368
    CC_OP_ADDB,
369
    CC_OP_SUBB,
370
    CC_OP_LOGICB,
371
    CC_OP_SUBB,
372
    CC_OP_LOGICB,
373
    CC_OP_SUBB,
374
};
375

    
376
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
377
    [OT_BYTE] = {
378
        gen_op_rolb_T0_T1_cc,
379
        gen_op_rorb_T0_T1_cc,
380
        gen_op_rclb_T0_T1_cc,
381
        gen_op_rcrb_T0_T1_cc,
382
        gen_op_shlb_T0_T1_cc,
383
        gen_op_shrb_T0_T1_cc,
384
        gen_op_shlb_T0_T1_cc,
385
        gen_op_sarb_T0_T1_cc,
386
    },
387
    [OT_WORD] = {
388
        gen_op_rolw_T0_T1_cc,
389
        gen_op_rorw_T0_T1_cc,
390
        gen_op_rclw_T0_T1_cc,
391
        gen_op_rcrw_T0_T1_cc,
392
        gen_op_shlw_T0_T1_cc,
393
        gen_op_shrw_T0_T1_cc,
394
        gen_op_shlw_T0_T1_cc,
395
        gen_op_sarw_T0_T1_cc,
396
    },
397
    [OT_LONG] = {
398
        gen_op_roll_T0_T1_cc,
399
        gen_op_rorl_T0_T1_cc,
400
        gen_op_rcll_T0_T1_cc,
401
        gen_op_rcrl_T0_T1_cc,
402
        gen_op_shll_T0_T1_cc,
403
        gen_op_shrl_T0_T1_cc,
404
        gen_op_shll_T0_T1_cc,
405
        gen_op_sarl_T0_T1_cc,
406
    },
407
};
408

    
409
static GenOpFunc *gen_op_lds_T0_A0[3] = {
410
    gen_op_ldsb_T0_A0,
411
    gen_op_ldsw_T0_A0,
412
};
413

    
414
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
415
    gen_op_ldub_T0_A0,
416
    gen_op_lduw_T0_A0,
417
};
418

    
419
/* sign does not matter */
420
static GenOpFunc *gen_op_ld_T0_A0[3] = {
421
    gen_op_ldub_T0_A0,
422
    gen_op_lduw_T0_A0,
423
    gen_op_ldl_T0_A0,
424
};
425

    
426
static GenOpFunc *gen_op_ld_T1_A0[3] = {
427
    gen_op_ldub_T1_A0,
428
    gen_op_lduw_T1_A0,
429
    gen_op_ldl_T1_A0,
430
};
431

    
432
static GenOpFunc *gen_op_st_T0_A0[3] = {
433
    gen_op_stb_T0_A0,
434
    gen_op_stw_T0_A0,
435
    gen_op_stl_T0_A0,
436
};
437

    
438
static GenOpFunc *gen_op_movs[6] = {
439
    gen_op_movsb,
440
    gen_op_movsw,
441
    gen_op_movsl,
442
    gen_op_rep_movsb,
443
    gen_op_rep_movsw,
444
    gen_op_rep_movsl,
445
};
446

    
447
static GenOpFunc *gen_op_stos[6] = {
448
    gen_op_stosb,
449
    gen_op_stosw,
450
    gen_op_stosl,
451
    gen_op_rep_stosb,
452
    gen_op_rep_stosw,
453
    gen_op_rep_stosl,
454
};
455

    
456
static GenOpFunc *gen_op_lods[6] = {
457
    gen_op_lodsb,
458
    gen_op_lodsw,
459
    gen_op_lodsl,
460
    gen_op_rep_lodsb,
461
    gen_op_rep_lodsw,
462
    gen_op_rep_lodsl,
463
};
464

    
465
static GenOpFunc *gen_op_scas[9] = {
466
    gen_op_scasb,
467
    gen_op_scasw,
468
    gen_op_scasl,
469
    gen_op_repz_scasb,
470
    gen_op_repz_scasw,
471
    gen_op_repz_scasl,
472
    gen_op_repnz_scasb,
473
    gen_op_repnz_scasw,
474
    gen_op_repnz_scasl,
475
};
476

    
477
static GenOpFunc *gen_op_cmps[9] = {
478
    gen_op_cmpsb,
479
    gen_op_cmpsw,
480
    gen_op_cmpsl,
481
    gen_op_repz_cmpsb,
482
    gen_op_repz_cmpsw,
483
    gen_op_repz_cmpsl,
484
    gen_op_repnz_cmpsb,
485
    gen_op_repnz_cmpsw,
486
    gen_op_repnz_cmpsl,
487
};
488

    
489
static GenOpFunc *gen_op_ins[6] = {
490
    gen_op_insb,
491
    gen_op_insw,
492
    gen_op_insl,
493
    gen_op_rep_insb,
494
    gen_op_rep_insw,
495
    gen_op_rep_insl,
496
};
497

    
498

    
499
static GenOpFunc *gen_op_outs[6] = {
500
    gen_op_outsb,
501
    gen_op_outsw,
502
    gen_op_outsl,
503
    gen_op_rep_outsb,
504
    gen_op_rep_outsw,
505
    gen_op_rep_outsl,
506
};
507

    
508
static GenOpFunc *gen_op_in[3] = {
509
    gen_op_inb_T0_T1,
510
    gen_op_inw_T0_T1,
511
    gen_op_inl_T0_T1,
512
};
513

    
514
static GenOpFunc *gen_op_out[3] = {
515
    gen_op_outb_T0_T1,
516
    gen_op_outw_T0_T1,
517
    gen_op_outl_T0_T1,
518
};
519

    
520
enum {
521
    JCC_O,
522
    JCC_B,
523
    JCC_Z,
524
    JCC_BE,
525
    JCC_S,
526
    JCC_P,
527
    JCC_L,
528
    JCC_LE,
529
};
530

    
531
static GenOpFunc2 *gen_jcc_slow[8] = {
532
    gen_op_jo_cc,
533
    gen_op_jb_cc,
534
    gen_op_jz_cc,
535
    gen_op_jbe_cc,
536
    gen_op_js_cc,
537
    gen_op_jp_cc,
538
    gen_op_jl_cc,
539
    gen_op_jle_cc,
540
};
541
    
542
static GenOpFunc2 *gen_jcc_sub[3][8] = {
543
    [OT_BYTE] = {
544
        NULL,
545
        gen_op_jb_subb,
546
        gen_op_jz_subb,
547
        gen_op_jbe_subb,
548
        gen_op_js_subb,
549
        NULL,
550
        gen_op_jl_subb,
551
        gen_op_jle_subb,
552
    },
553
    [OT_WORD] = {
554
        NULL,
555
        gen_op_jb_subw,
556
        gen_op_jz_subw,
557
        gen_op_jbe_subw,
558
        gen_op_js_subw,
559
        NULL,
560
        gen_op_jl_subw,
561
        gen_op_jle_subw,
562
    },
563
    [OT_LONG] = {
564
        NULL,
565
        gen_op_jb_subl,
566
        gen_op_jz_subl,
567
        gen_op_jbe_subl,
568
        gen_op_js_subl,
569
        NULL,
570
        gen_op_jl_subl,
571
        gen_op_jle_subl,
572
    },
573
};
574

    
575
static GenOpFunc *gen_setcc_slow[8] = {
576
    gen_op_seto_T0_cc,
577
    gen_op_setb_T0_cc,
578
    gen_op_setz_T0_cc,
579
    gen_op_setbe_T0_cc,
580
    gen_op_sets_T0_cc,
581
    gen_op_setp_T0_cc,
582
    gen_op_setl_T0_cc,
583
    gen_op_setle_T0_cc,
584
};
585

    
586
static GenOpFunc *gen_setcc_sub[3][8] = {
587
    [OT_BYTE] = {
588
        NULL,
589
        gen_op_setb_T0_subb,
590
        gen_op_setz_T0_subb,
591
        gen_op_setbe_T0_subb,
592
        gen_op_sets_T0_subb,
593
        NULL,
594
        gen_op_setl_T0_subb,
595
        gen_op_setle_T0_subb,
596
    },
597
    [OT_WORD] = {
598
        NULL,
599
        gen_op_setb_T0_subw,
600
        gen_op_setz_T0_subw,
601
        gen_op_setbe_T0_subw,
602
        gen_op_sets_T0_subw,
603
        NULL,
604
        gen_op_setl_T0_subw,
605
        gen_op_setle_T0_subw,
606
    },
607
    [OT_LONG] = {
608
        NULL,
609
        gen_op_setb_T0_subl,
610
        gen_op_setz_T0_subl,
611
        gen_op_setbe_T0_subl,
612
        gen_op_sets_T0_subl,
613
        NULL,
614
        gen_op_setl_T0_subl,
615
        gen_op_setle_T0_subl,
616
    },
617
};
618

    
619
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
620
    gen_op_fadd_ST0_FT0,
621
    gen_op_fmul_ST0_FT0,
622
    gen_op_fcom_ST0_FT0,
623
    gen_op_fcom_ST0_FT0,
624
    gen_op_fsub_ST0_FT0,
625
    gen_op_fsubr_ST0_FT0,
626
    gen_op_fdiv_ST0_FT0,
627
    gen_op_fdivr_ST0_FT0,
628
};
629

    
630
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
631
    gen_op_fadd_STN_ST0,
632
    gen_op_fmul_STN_ST0,
633
    NULL,
634
    NULL,
635
    gen_op_fsub_STN_ST0,
636
    gen_op_fsubr_STN_ST0,
637
    gen_op_fdiv_STN_ST0,
638
    gen_op_fdivr_STN_ST0,
639
};
640

    
641
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
642
{
643
    if (d != OR_TMP0)
644
        gen_op_mov_TN_reg[ot][0][d]();
645
    if (s != OR_TMP1)
646
        gen_op_mov_TN_reg[ot][1][s]();
647
    if ((op == OP_ADCL || op == OP_SBBL) && s1->cc_op != CC_OP_DYNAMIC)
648
        gen_op_set_cc_op(s1->cc_op);
649
    gen_op_arith_T0_T1_cc[op]();
650
    if (d != OR_TMP0 && op != OP_CMPL)
651
        gen_op_mov_reg_T0[ot][d]();
652
    s1->cc_op = cc_op_arithb[op] + ot;
653
}
654

    
655
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
656
{
657
    gen_op_movl_T1_im(c);
658
    gen_op(s1, op, ot, d, OR_TMP0);
659
}
660

    
661
static void gen_inc(DisasContext *s1, int ot, int d, int c)
662
{
663
    if (d != OR_TMP0)
664
        gen_op_mov_TN_reg[ot][0][d]();
665
    if (s1->cc_op != CC_OP_DYNAMIC)
666
        gen_op_set_cc_op(s1->cc_op);
667
    if (c > 0)
668
        gen_op_incl_T0_cc();
669
    else
670
        gen_op_decl_T0_cc();
671
    if (d != OR_TMP0)
672
        gen_op_mov_reg_T0[ot][d]();
673
}
674

    
675
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
676
{
677
    if (d != OR_TMP0)
678
        gen_op_mov_TN_reg[ot][0][d]();
679
    if (s != OR_TMP1)
680
        gen_op_mov_TN_reg[ot][1][s]();
681
    switch(op) {
682
    case OP_ROL:
683
    case OP_ROR:
684
    case OP_RCL:
685
    case OP_RCR:
686
        /* only C and O are modified, so we must update flags dynamically */
687
        if (s1->cc_op != CC_OP_DYNAMIC)
688
            gen_op_set_cc_op(s1->cc_op);
689
        gen_op_shift_T0_T1_cc[ot][op]();
690
        break;
691
    default:
692
        gen_op_shift_T0_T1_cc[ot][op]();
693
        break;
694
    }
695
    if (d != OR_TMP0)
696
        gen_op_mov_reg_T0[ot][d]();
697
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
698
}
699

    
700
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
701
{
702
    /* currently not optimized */
703
    gen_op_movl_T1_im(c);
704
    gen_shift(s1, op, ot, d, OR_TMP1);
705
}
706

    
707
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
708
{
709
    int havesib;
710
    int havebase;
711
    int base, disp;
712
    int index = 0;
713
    int scale = 0;
714
    int reg1, reg2, opreg;
715
    int mod, rm, code;
716

    
717
    mod = (modrm >> 6) & 3;
718
    rm = modrm & 7;
719

    
720
    if (s->aflag) {
721

    
722
        havesib = 0;
723
        havebase = 1;
724
        base = rm;
725
        
726
        if (base == 4) {
727
            havesib = 1;
728
            code = ldub(s->pc++);
729
            scale = (code >> 6) & 3;
730
            index = (code >> 3) & 7;
731
            base = code & 7;
732
        }
733

    
734
        switch (mod) {
735
        case 0:
736
            if (base == 5) {
737
                havebase = 0;
738
                disp = ldl(s->pc);
739
                s->pc += 4;
740
            } else {
741
                disp = 0;
742
            }
743
            break;
744
        case 1:
745
            disp = (int8_t)ldub(s->pc++);
746
            break;
747
        default:
748
        case 2:
749
            disp = ldl(s->pc);
750
            s->pc += 4;
751
            break;
752
        }
753

    
754
        reg1 = OR_ZERO;
755
        reg2 = OR_ZERO;
756
          
757
        if (havebase || (havesib && (index != 4 || scale != 0))) {
758
            if (havebase)
759
                reg1 = OR_EAX + base;
760
            if (havesib && index != 4) {
761
                if (havebase)
762
                    reg2 = index + OR_EAX;
763
                else
764
                    reg1 = index + OR_EAX;
765
            }
766
        }
767
        /* XXX: disp only ? */
768
        if (reg2 == OR_ZERO) {
769
            /* op: disp + (reg1 << scale) */
770
            if (reg1 == OR_ZERO) {
771
                gen_op_movl_A0_im(disp);
772
            } else if (scale == 0 && disp == 0) {
773
                gen_op_movl_A0_reg[reg1]();
774
            } else {
775
                gen_op_movl_A0_im(disp);
776
                gen_op_addl_A0_reg_sN[scale][reg1]();
777
            }
778
        } else {
779
            /* op: disp + reg1 + (reg2 << scale) */
780
            if (disp != 0) {
781
                gen_op_movl_A0_im(disp);
782
                gen_op_addl_A0_reg_sN[0][reg1]();
783
            } else {
784
                gen_op_movl_A0_reg[reg1]();
785
            }
786
            gen_op_addl_A0_reg_sN[scale][reg2]();
787
        }
788
        opreg = OR_A0;
789
    } else {
790
        fprintf(stderr, "16 bit addressing not supported\n");
791
        disp = 0;
792
        opreg = 0;
793
    }
794
    *reg_ptr = opreg;
795
    *offset_ptr = disp;
796
}
797

    
798
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
799
   OR_TMP0 */
800
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
801
{
802
    int mod, rm, opreg, disp;
803

    
804
    mod = (modrm >> 6) & 3;
805
    rm = modrm & 7;
806
    if (mod == 3) {
807
        if (is_store) {
808
            if (reg != OR_TMP0)
809
                gen_op_mov_TN_reg[ot][0][reg]();
810
            gen_op_mov_reg_T0[ot][rm]();
811
        } else {
812
            gen_op_mov_TN_reg[ot][0][rm]();
813
            if (reg != OR_TMP0)
814
                gen_op_mov_reg_T0[ot][reg]();
815
        }
816
    } else {
817
        gen_lea_modrm(s, modrm, &opreg, &disp);
818
        if (is_store) {
819
            if (reg != OR_TMP0)
820
                gen_op_mov_TN_reg[ot][0][reg]();
821
            gen_op_st_T0_A0[ot]();
822
        } else {
823
            gen_op_ld_T0_A0[ot]();
824
            if (reg != OR_TMP0)
825
                gen_op_mov_reg_T0[ot][reg]();
826
        }
827
    }
828
}
829

    
830
static inline uint32_t insn_get(DisasContext *s, int ot)
831
{
832
    uint32_t ret;
833

    
834
    switch(ot) {
835
    case OT_BYTE:
836
        ret = ldub(s->pc);
837
        s->pc++;
838
        break;
839
    case OT_WORD:
840
        ret = lduw(s->pc);
841
        s->pc += 2;
842
        break;
843
    default:
844
    case OT_LONG:
845
        ret = ldl(s->pc);
846
        s->pc += 4;
847
        break;
848
    }
849
    return ret;
850
}
851

    
852
static void gen_jcc(DisasContext *s, int b, int val)
853
{
854
    int inv, jcc_op;
855
    GenOpFunc2 *func;
856

    
857
    inv = b & 1;
858
    jcc_op = (b >> 1) & 7;
859
    switch(s->cc_op) {
860
        /* we optimize the cmp/jcc case */
861
    case CC_OP_SUBB:
862
    case CC_OP_SUBW:
863
    case CC_OP_SUBL:
864
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
865
        if (!func)
866
            goto slow_jcc;
867
        break;
868
        
869
        /* some jumps are easy to compute */
870
    case CC_OP_ADDB:
871
    case CC_OP_ADDW:
872
    case CC_OP_ADDL:
873
    case CC_OP_LOGICB:
874
    case CC_OP_LOGICW:
875
    case CC_OP_LOGICL:
876
    case CC_OP_INCB:
877
    case CC_OP_INCW:
878
    case CC_OP_INCL:
879
    case CC_OP_DECB:
880
    case CC_OP_DECW:
881
    case CC_OP_DECL:
882
    case CC_OP_SHLB:
883
    case CC_OP_SHLW:
884
    case CC_OP_SHLL:
885
        switch(jcc_op) {
886
        case JCC_Z:
887
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
888
            break;
889
        case JCC_S:
890
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
891
            break;
892
        default:
893
            goto slow_jcc;
894
        }
895
        break;
896
    default:
897
    slow_jcc:
898
        if (s->cc_op != CC_OP_DYNAMIC)
899
            op_set_cc_op(s->cc_op);
900
        func = gen_jcc_slow[jcc_op];
901
        break;
902
    }
903
    if (!inv) {
904
        func(val, (long)s->pc);
905
    } else {
906
        func((long)s->pc, val);
907
    }
908
}
909

    
910
static void gen_setcc(DisasContext *s, int b)
911
{
912
    int inv, jcc_op;
913
    GenOpFunc *func;
914

    
915
    inv = b & 1;
916
    jcc_op = (b >> 1) & 7;
917
    switch(s->cc_op) {
918
        /* we optimize the cmp/jcc case */
919
    case CC_OP_SUBB:
920
    case CC_OP_SUBW:
921
    case CC_OP_SUBL:
922
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
923
        if (!func)
924
            goto slow_jcc;
925
        break;
926
        
927
        /* some jumps are easy to compute */
928
    case CC_OP_ADDB:
929
    case CC_OP_ADDW:
930
    case CC_OP_ADDL:
931
    case CC_OP_LOGICB:
932
    case CC_OP_LOGICW:
933
    case CC_OP_LOGICL:
934
    case CC_OP_INCB:
935
    case CC_OP_INCW:
936
    case CC_OP_INCL:
937
    case CC_OP_DECB:
938
    case CC_OP_DECW:
939
    case CC_OP_DECL:
940
    case CC_OP_SHLB:
941
    case CC_OP_SHLW:
942
    case CC_OP_SHLL:
943
        switch(jcc_op) {
944
        case JCC_Z:
945
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
946
            break;
947
        case JCC_S:
948
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
949
            break;
950
        default:
951
            goto slow_jcc;
952
        }
953
        break;
954
    default:
955
    slow_jcc:
956
        if (s->cc_op != CC_OP_DYNAMIC)
957
            op_set_cc_op(s->cc_op);
958
        func = gen_setcc_slow[jcc_op];
959
        break;
960
    }
961
    func();
962
    if (inv) {
963
        gen_op_xor_T0_1();
964
    }
965
}
966

    
967
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
968
   is set to true if the instruction sets the PC (last instruction of
969
   a basic block) */
970
long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
971
{
972
    int b, prefixes, aflag, dflag;
973
    int shift, ot;
974
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
975

    
976
    s->pc = pc_start;
977
    prefixes = 0;
978
    aflag = 1;
979
    dflag = 1;
980
    //    cur_pc = s->pc; /* for insn generation */
981
 next_byte:
982
    b = ldub(s->pc);
983
    s->pc++;
984
    /* check prefixes */
985
    switch (b) {
986
    case 0xf3:
987
        prefixes |= PREFIX_REPZ;
988
        goto next_byte;
989
    case 0xf2:
990
        prefixes |= PREFIX_REPNZ;
991
        goto next_byte;
992
    case 0xf0:
993
        prefixes |= PREFIX_LOCK;
994
        goto next_byte;
995
    case 0x2e:
996
        prefixes |= PREFIX_CS;
997
        goto next_byte;
998
    case 0x36:
999
        prefixes |= PREFIX_SS;
1000
        goto next_byte;
1001
    case 0x3e:
1002
        prefixes |= PREFIX_DS;
1003
        goto next_byte;
1004
    case 0x26:
1005
        prefixes |= PREFIX_ES;
1006
        goto next_byte;
1007
    case 0x64:
1008
        prefixes |= PREFIX_FS;
1009
        goto next_byte;
1010
    case 0x65:
1011
        prefixes |= PREFIX_GS;
1012
        goto next_byte;
1013
    case 0x66:
1014
        prefixes |= PREFIX_DATA;
1015
        goto next_byte;
1016
    case 0x67:
1017
        prefixes |= PREFIX_ADR;
1018
        goto next_byte;
1019
    case 0x9b:
1020
        prefixes |= PREFIX_FWAIT;
1021
        goto next_byte;
1022
    }
1023

    
1024
    if (prefixes & PREFIX_DATA)
1025
        dflag ^= 1;
1026
    if (prefixes & PREFIX_ADR)
1027
        aflag ^= 1;
1028

    
1029
    s->prefix = prefixes;
1030
    s->aflag = aflag;
1031
    s->dflag = dflag;
1032

    
1033
    /* now check op code */
1034
 reswitch:
1035
    switch(b) {
1036
    case 0x0f:
1037
        /**************************/
1038
        /* extended op code */
1039
        b = ldub(s->pc++) | 0x100;
1040
        goto reswitch;
1041
        
1042
        /**************************/
1043
        /* arith & logic */
1044
    case 0x00 ... 0x05:
1045
    case 0x08 ... 0x0d:
1046
    case 0x10 ... 0x15:
1047
    case 0x18 ... 0x1d:
1048
    case 0x20 ... 0x25:
1049
    case 0x28 ... 0x2d:
1050
    case 0x30 ... 0x35:
1051
    case 0x38 ... 0x3d:
1052
        {
1053
            int op, f, val;
1054
            op = (b >> 3) & 7;
1055
            f = (b >> 1) & 3;
1056

    
1057
            if ((b & 1) == 0)
1058
                ot = OT_BYTE;
1059
            else
1060
                ot = dflag ? OT_LONG : OT_WORD;
1061
            
1062
            switch(f) {
1063
            case 0: /* OP Ev, Gv */
1064
                modrm = ldub(s->pc++);
1065
                reg = ((modrm >> 3) & 7) + OR_EAX;
1066
                mod = (modrm >> 6) & 3;
1067
                rm = modrm & 7;
1068
                if (mod != 3) {
1069
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1070
                    gen_op_ld_T0_A0[ot]();
1071
                    opreg = OR_TMP0;
1072
                } else {
1073
                    opreg = OR_EAX + rm;
1074
                }
1075
                gen_op(s, op, ot, opreg, reg);
1076
                if (mod != 3 && op != 7) {
1077
                    gen_op_st_T0_A0[ot]();
1078
                }
1079
                break;
1080
            case 1: /* OP Gv, Ev */
1081
                modrm = ldub(s->pc++);
1082
                mod = (modrm >> 6) & 3;
1083
                reg = ((modrm >> 3) & 7) + OR_EAX;
1084
                rm = modrm & 7;
1085
                if (mod != 3) {
1086
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1087
                    gen_op_ld_T1_A0[ot]();
1088
                    opreg = OR_TMP1;
1089
                } else {
1090
                    opreg = OR_EAX + rm;
1091
                }
1092
                gen_op(s, op, ot, reg, opreg);
1093
                break;
1094
            case 2: /* OP A, Iv */
1095
                val = insn_get(s, ot);
1096
                gen_opi(s, op, ot, OR_EAX, val);
1097
                break;
1098
            }
1099
        }
1100
        break;
1101

    
1102
    case 0x80: /* GRP1 */
1103
    case 0x81:
1104
    case 0x83:
1105
        {
1106
            int val;
1107

    
1108
            if ((b & 1) == 0)
1109
                ot = OT_BYTE;
1110
            else
1111
                ot = dflag ? OT_LONG : OT_WORD;
1112
            
1113
            modrm = ldub(s->pc++);
1114
            mod = (modrm >> 6) & 3;
1115
            rm = modrm & 7;
1116
            op = (modrm >> 3) & 7;
1117
            
1118
            if (mod != 3) {
1119
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1120
                gen_op_ld_T0_A0[ot]();
1121
                opreg = OR_TMP0;
1122
            } else {
1123
                opreg = rm + OR_EAX;
1124
            }
1125

    
1126
            switch(b) {
1127
            default:
1128
            case 0x80:
1129
            case 0x81:
1130
                val = insn_get(s, ot);
1131
                break;
1132
            case 0x83:
1133
                val = (int8_t)insn_get(s, OT_BYTE);
1134
                break;
1135
            }
1136

    
1137
            gen_opi(s, op, ot, opreg, val);
1138
            if (op != 7 && mod != 3) {
1139
                gen_op_st_T0_A0[ot]();
1140
            }
1141
        }
1142
        break;
1143

    
1144
        /**************************/
1145
        /* inc, dec, and other misc arith */
1146
    case 0x40 ... 0x47: /* inc Gv */
1147
        ot = dflag ? OT_LONG : OT_WORD;
1148
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1149
        break;
1150
    case 0x48 ... 0x4f: /* dec Gv */
1151
        ot = dflag ? OT_LONG : OT_WORD;
1152
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1153
        break;
1154
    case 0xf6: /* GRP3 */
1155
    case 0xf7:
1156
        if ((b & 1) == 0)
1157
            ot = OT_BYTE;
1158
        else
1159
            ot = dflag ? OT_LONG : OT_WORD;
1160

    
1161
        modrm = ldub(s->pc++);
1162
        mod = (modrm >> 6) & 3;
1163
        rm = modrm & 7;
1164
        op = (modrm >> 3) & 7;
1165
        if (mod != 3) {
1166
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1167
            gen_op_ld_T0_A0[ot]();
1168
        } else {
1169
            gen_op_mov_TN_reg[ot][0][rm]();
1170
        }
1171

    
1172
        switch(op) {
1173
        case 0: /* test */
1174
            val = insn_get(s, ot);
1175
            gen_op_movl_T1_im(val);
1176
            gen_op_testl_T0_T1_cc();
1177
            s->cc_op = CC_OP_LOGICB + ot;
1178
            break;
1179
        case 2: /* not */
1180
            gen_op_notl_T0();
1181
            if (mod != 3) {
1182
                gen_op_st_T0_A0[ot]();
1183
            } else {
1184
                gen_op_mov_reg_T0[ot][rm]();
1185
            }
1186
            break;
1187
        case 3: /* neg */
1188
            gen_op_negl_T0_cc();
1189
            if (mod != 3) {
1190
                gen_op_st_T0_A0[ot]();
1191
            } else {
1192
                gen_op_mov_reg_T0[ot][rm]();
1193
            }
1194
            s->cc_op = CC_OP_SUBB + ot;
1195
            break;
1196
        case 4: /* mul */
1197
            switch(ot) {
1198
            case OT_BYTE:
1199
                gen_op_mulb_AL_T0();
1200
                break;
1201
            case OT_WORD:
1202
                gen_op_mulw_AX_T0();
1203
                break;
1204
            default:
1205
            case OT_LONG:
1206
                gen_op_mull_EAX_T0();
1207
                break;
1208
            }
1209
            s->cc_op = CC_OP_MUL;
1210
            break;
1211
        case 5: /* imul */
1212
            switch(ot) {
1213
            case OT_BYTE:
1214
                gen_op_imulb_AL_T0();
1215
                break;
1216
            case OT_WORD:
1217
                gen_op_imulw_AX_T0();
1218
                break;
1219
            default:
1220
            case OT_LONG:
1221
                gen_op_imull_EAX_T0();
1222
                break;
1223
            }
1224
            s->cc_op = CC_OP_MUL;
1225
            break;
1226
        case 6: /* div */
1227
            switch(ot) {
1228
            case OT_BYTE:
1229
                gen_op_divb_AL_T0();
1230
                break;
1231
            case OT_WORD:
1232
                gen_op_divw_AX_T0();
1233
                break;
1234
            default:
1235
            case OT_LONG:
1236
                gen_op_divl_EAX_T0();
1237
                break;
1238
            }
1239
            break;
1240
        case 7: /* idiv */
1241
            switch(ot) {
1242
            case OT_BYTE:
1243
                gen_op_idivb_AL_T0();
1244
                break;
1245
            case OT_WORD:
1246
                gen_op_idivw_AX_T0();
1247
                break;
1248
            default:
1249
            case OT_LONG:
1250
                gen_op_idivl_EAX_T0();
1251
                break;
1252
            }
1253
            break;
1254
        default:
1255
            error("GRP3: bad instruction");
1256
            return -1;
1257
        }
1258
        break;
1259

    
1260
    case 0xfe: /* GRP4 */
1261
    case 0xff: /* GRP5 */
1262
        if ((b & 1) == 0)
1263
            ot = OT_BYTE;
1264
        else
1265
            ot = dflag ? OT_LONG : OT_WORD;
1266

    
1267
        modrm = ldub(s->pc++);
1268
        mod = (modrm >> 6) & 3;
1269
        rm = modrm & 7;
1270
        op = (modrm >> 3) & 7;
1271
        if (op >= 2 && b == 0xfe) {
1272
            error("GRP4: bad instruction");
1273
            return -1;
1274
        }
1275
        if (mod != 3) {
1276
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1277
            gen_op_ld_T0_A0[ot]();
1278
        } else {
1279
            gen_op_mov_TN_reg[ot][0][rm]();
1280
        }
1281

    
1282
        switch(op) {
1283
        case 0: /* inc Ev */
1284
            gen_inc(s, ot, OR_TMP0, 1);
1285
            if (mod != 3)
1286
                gen_op_st_T0_A0[ot]();
1287
            break;
1288
        case 1: /* dec Ev */
1289
            gen_inc(s, ot, OR_TMP0, -1);
1290
            if (mod != 3)
1291
                gen_op_st_T0_A0[ot]();
1292
            break;
1293
        case 2: /* call Ev */
1294
            gen_op_movl_T1_im((long)s->pc);
1295
            gen_op_pushl_T1();
1296
            gen_op_jmp_T0();
1297
            *is_jmp_ptr = 1;
1298
            break;
1299
        case 4: /* jmp Ev */
1300
            gen_op_jmp_T0();
1301
            *is_jmp_ptr = 1;
1302
            break;
1303
        case 6: /* push Ev */
1304
            gen_op_pushl_T0();
1305
            break;
1306
        default:
1307
            error("GRP5: bad instruction");
1308
            return -1;
1309
        }
1310
        break;
1311

    
1312
    case 0x84: /* test Ev, Gv */
1313
    case 0x85: 
1314
        if ((b & 1) == 0)
1315
            ot = OT_BYTE;
1316
        else
1317
            ot = dflag ? OT_LONG : OT_WORD;
1318

    
1319
        modrm = ldub(s->pc++);
1320
        mod = (modrm >> 6) & 3;
1321
        rm = modrm & 7;
1322
        reg = (modrm >> 3) & 7;
1323
        
1324
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1325
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1326
        gen_op_testl_T0_T1_cc();
1327
        s->cc_op = CC_OP_LOGICB + ot;
1328
        break;
1329
        
1330
    case 0xa8: /* test eAX, Iv */
1331
    case 0xa9:
1332
        if ((b & 1) == 0)
1333
            ot = OT_BYTE;
1334
        else
1335
            ot = dflag ? OT_LONG : OT_WORD;
1336
        val = insn_get(s, ot);
1337

    
1338
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1339
        gen_op_movl_T1_im(val);
1340
        gen_op_testl_T0_T1_cc();
1341
        s->cc_op = CC_OP_LOGICB + ot;
1342
        break;
1343
        
1344
    case 0x98: /* CWDE/CBW */
1345
        if (dflag)
1346
            gen_op_movswl_EAX_AX();
1347
        else
1348
            gen_op_movsbw_AX_AL();
1349
        break;
1350
    case 0x99: /* CDQ/CWD */
1351
        if (dflag)
1352
            gen_op_movslq_EDX_EAX();
1353
        else
1354
            gen_op_movswl_DX_AX();
1355
        break;
1356
    case 0x1af: /* imul Gv, Ev */
1357
    case 0x69: /* imul Gv, Ev, I */
1358
    case 0x6b:
1359
        ot = dflag ? OT_LONG : OT_WORD;
1360
        modrm = ldub(s->pc++);
1361
        reg = ((modrm >> 3) & 7) + OR_EAX;
1362
        
1363
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1364
        if (b == 0x69) {
1365
            val = insn_get(s, ot);
1366
            gen_op_movl_T1_im(val);
1367
        } else if (b == 0x6b) {
1368
            val = insn_get(s, OT_BYTE);
1369
            gen_op_movl_T1_im(val);
1370
        } else {
1371
            gen_op_mov_TN_reg[ot][1][reg]();
1372
        }
1373

    
1374
        if (ot == OT_LONG) {
1375
            op_imull_T0_T1();
1376
        } else {
1377
            op_imulw_T0_T1();
1378
        }
1379
        gen_op_mov_reg_T0[ot][reg]();
1380
        s->cc_op = CC_OP_MUL;
1381
        break;
1382
        
1383
        /**************************/
1384
        /* push/pop */
1385
    case 0x50 ... 0x57: /* push */
1386
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1387
        gen_op_pushl_T0();
1388
        break;
1389
    case 0x58 ... 0x5f: /* pop */
1390
        gen_op_popl_T0();
1391
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1392
        break;
1393
    case 0x68: /* push Iv */
1394
    case 0x6a:
1395
        ot = dflag ? OT_LONG : OT_WORD;
1396
        if (b == 0x68)
1397
            val = insn_get(s, ot);
1398
        else
1399
            val = (int8_t)insn_get(s, OT_BYTE);
1400
        gen_op_movl_T0_im(val);
1401
        gen_op_pushl_T0();
1402
        break;
1403
    case 0x8f: /* pop Ev */
1404
        ot = dflag ? OT_LONG : OT_WORD;
1405
        modrm = ldub(s->pc++);
1406
        gen_op_popl_T0();
1407
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1408
        break;
1409
    case 0xc9: /* leave */
1410
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1411
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1412
        gen_op_popl_T0();
1413
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1414
        break;
1415
        /**************************/
1416
        /* mov */
1417
    case 0x88:
1418
    case 0x89: /* mov Gv, Ev */
1419
        if ((b & 1) == 0)
1420
            ot = OT_BYTE;
1421
        else
1422
            ot = dflag ? OT_LONG : OT_WORD;
1423
        modrm = ldub(s->pc++);
1424
        reg = (modrm >> 3) & 7;
1425
        
1426
        /* generate a generic store */
1427
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1428
        break;
1429
    case 0xc6:
1430
    case 0xc7: /* mov Ev, Iv */
1431
        if ((b & 1) == 0)
1432
            ot = OT_BYTE;
1433
        else
1434
            ot = dflag ? OT_LONG : OT_WORD;
1435
        modrm = ldub(s->pc++);
1436
        mod = (modrm >> 6) & 3;
1437
        if (mod != 3)
1438
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1439
        val = insn_get(s, ot);
1440
        gen_op_movl_T0_im(val);
1441
        if (mod != 3)
1442
            gen_op_st_T0_A0[ot]();
1443
        else
1444
            gen_op_mov_reg_T0[ot][modrm & 7]();
1445
        break;
1446
    case 0x8a:
1447
    case 0x8b: /* mov Ev, Gv */
1448
        if ((b & 1) == 0)
1449
            ot = OT_BYTE;
1450
        else
1451
            ot = dflag ? OT_LONG : OT_WORD;
1452
        modrm = ldub(s->pc++);
1453
        reg = (modrm >> 3) & 7;
1454
        
1455
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1456
        gen_op_mov_reg_T0[ot][reg]();
1457
        break;
1458

    
1459
    case 0x1b6: /* movzbS Gv, Eb */
1460
    case 0x1b7: /* movzwS Gv, Eb */
1461
    case 0x1be: /* movsbS Gv, Eb */
1462
    case 0x1bf: /* movswS Gv, Eb */
1463
        {
1464
            int d_ot;
1465
            /* d_ot is the size of destination */
1466
            d_ot = dflag + OT_WORD;
1467
            /* ot is the size of source */
1468
            ot = (b & 1) + OT_BYTE;
1469
            modrm = ldub(s->pc++);
1470
            reg = ((modrm >> 3) & 7) + OR_EAX;
1471
            mod = (modrm >> 6) & 3;
1472
            rm = modrm & 7;
1473
            
1474
            if (mod == 3) {
1475
                gen_op_mov_TN_reg[ot][0][rm]();
1476
                switch(ot | (b & 8)) {
1477
                case OT_BYTE:
1478
                    gen_op_movzbl_T0_T0();
1479
                    break;
1480
                case OT_BYTE | 8:
1481
                    gen_op_movsbl_T0_T0();
1482
                    break;
1483
                case OT_WORD:
1484
                    gen_op_movzwl_T0_T0();
1485
                    break;
1486
                default:
1487
                case OT_WORD | 8:
1488
                    gen_op_movswl_T0_T0();
1489
                    break;
1490
                }
1491
                gen_op_mov_reg_T0[d_ot][reg]();
1492
            } else {
1493
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1494
                if (b & 8) {
1495
                    gen_op_lds_T0_A0[ot]();
1496
                } else {
1497
                    gen_op_ldu_T0_A0[ot]();
1498
                }
1499
                gen_op_mov_reg_T0[d_ot][reg]();
1500
            }
1501
        }
1502
        break;
1503

    
1504
    case 0x8d: /* lea */
1505
        ot = dflag ? OT_LONG : OT_WORD;
1506
        modrm = ldub(s->pc++);
1507
        reg = (modrm >> 3) & 7;
1508

    
1509
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1510
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1511
        break;
1512
        
1513
    case 0xa0: /* mov EAX, Ov */
1514
    case 0xa1:
1515
    case 0xa2: /* mov Ov, EAX */
1516
    case 0xa3:
1517
        if ((b & 1) == 0)
1518
            ot = OT_BYTE;
1519
        else
1520
            ot = dflag ? OT_LONG : OT_WORD;
1521
        if (s->aflag)
1522
            offset_addr = insn_get(s, OT_LONG);
1523
        else
1524
            offset_addr = insn_get(s, OT_WORD);
1525
            
1526
        if ((b & 2) == 0) {
1527
            gen_op_ld_T0_A0[ot]();
1528
            gen_op_mov_reg_T0[ot][R_EAX]();
1529
        } else {
1530
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1531
            gen_op_st_T0_A0[ot]();
1532
        }
1533
        break;
1534

    
1535
    case 0xb0 ... 0xb7: /* mov R, Ib */
1536
        val = insn_get(s, OT_BYTE);
1537
        gen_op_movl_T0_im(val);
1538
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1539
        break;
1540
    case 0xb8 ... 0xbf: /* mov R, Iv */
1541
        ot = dflag ? OT_LONG : OT_WORD;
1542
        val = insn_get(s, ot);
1543
        reg = OR_EAX + (b & 7);
1544
        gen_op_movl_T0_im(val);
1545
        gen_op_mov_reg_T0[ot][reg]();
1546
        break;
1547

    
1548
    case 0x91 ... 0x97: /* xchg R, EAX */
1549
        ot = dflag ? OT_LONG : OT_WORD;
1550
        reg = b & 7;
1551
        gen_op_mov_TN_reg[ot][0][reg]();
1552
        gen_op_mov_TN_reg[ot][1][R_EAX]();
1553
        gen_op_mov_reg_T0[ot][R_EAX]();
1554
        gen_op_mov_reg_T1[ot][reg]();
1555
        break;
1556
    case 0x86:
1557
    case 0x87: /* xchg Ev, Gv */
1558
        if ((b & 1) == 0)
1559
            ot = OT_BYTE;
1560
        else
1561
            ot = dflag ? OT_LONG : OT_WORD;
1562
        modrm = ldub(s->pc++);
1563
        reg = (modrm >> 3) & 7;
1564

    
1565
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1566
        gen_op_mov_TN_reg[ot][0][reg]();
1567
        gen_op_ld_T1_A0[ot]();
1568
        gen_op_st_T0_A0[ot]();
1569
        gen_op_mov_reg_T1[ot][reg]();
1570
        break;
1571
        
1572
        /************************/
1573
        /* shifts */
1574
    case 0xc0:
1575
    case 0xc1:
1576
        /* shift Ev,Ib */
1577
        shift = 2;
1578
    grp2:
1579
        {
1580
            if ((b & 1) == 0)
1581
                ot = OT_BYTE;
1582
            else
1583
                ot = dflag ? OT_LONG : OT_WORD;
1584
            
1585
            modrm = ldub(s->pc++);
1586
            mod = (modrm >> 6) & 3;
1587
            rm = modrm & 7;
1588
            op = (modrm >> 3) & 7;
1589
            
1590
            if (mod != 3) {
1591
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1592
                gen_op_ld_T0_A0[ot]();
1593
                opreg = OR_TMP0;
1594
            } else {
1595
                opreg = rm + OR_EAX;
1596
            }
1597

    
1598
            /* simpler op */
1599
            if (shift == 0) {
1600
                gen_shift(s, op, ot, opreg, OR_ECX);
1601
            } else {
1602
                if (shift == 2) {
1603
                    shift = ldub(s->pc++);
1604
                }
1605
                gen_shifti(s, op, ot, opreg, shift);
1606
            }
1607

    
1608
            if (mod != 3) {
1609
                gen_op_st_T0_A0[ot]();
1610
            }
1611
        }
1612
        break;
1613
    case 0xd0:
1614
    case 0xd1:
1615
        /* shift Ev,1 */
1616
        shift = 1;
1617
        goto grp2;
1618
    case 0xd2:
1619
    case 0xd3:
1620
        /* shift Ev,cl */
1621
        shift = 0;
1622
        goto grp2;
1623

    
1624
        /************************/
1625
        /* floats */
1626
    case 0xd8 ... 0xdf: 
1627
        modrm = ldub(s->pc++);
1628
        mod = (modrm >> 6) & 3;
1629
        rm = modrm & 7;
1630
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1631
        
1632
        if (mod != 3) {
1633
            /* memory op */
1634
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1635
            switch(op) {
1636
            case 0x00 ... 0x07: /* fxxxs */
1637
            case 0x10 ... 0x17: /* fixxxl */
1638
            case 0x20 ... 0x27: /* fxxxl */
1639
            case 0x30 ... 0x37: /* fixxx */
1640
                {
1641
                    int op1;
1642
                    op1 = op & 7;
1643

    
1644
                    switch(op >> 4) {
1645
                    case 0:
1646
                        gen_op_flds_FT0_A0();
1647
                        break;
1648
                    case 1:
1649
                        gen_op_fildl_FT0_A0();
1650
                        break;
1651
                    case 2:
1652
                        gen_op_fldl_FT0_A0();
1653
                        break;
1654
                    case 3:
1655
                    default:
1656
                        gen_op_fild_FT0_A0();
1657
                        break;
1658
                    }
1659
                    
1660
                    gen_op_fp_arith_ST0_FT0[op1]();
1661
                    if (op1 == 3) {
1662
                        /* fcomp needs pop */
1663
                        gen_op_fpop();
1664
                    }
1665
                }
1666
                break;
1667
            case 0x08: /* flds */
1668
            case 0x0a: /* fsts */
1669
            case 0x0b: /* fstps */
1670
            case 0x18: /* fildl */
1671
            case 0x1a: /* fistl */
1672
            case 0x1b: /* fistpl */
1673
            case 0x28: /* fldl */
1674
            case 0x2a: /* fstl */
1675
            case 0x2b: /* fstpl */
1676
            case 0x38: /* filds */
1677
            case 0x3a: /* fists */
1678
            case 0x3b: /* fistps */
1679
                
1680
                switch(op & 7) {
1681
                case 0:
1682
                    gen_op_fpush();
1683
                    switch(op >> 4) {
1684
                    case 0:
1685
                        gen_op_flds_ST0_A0();
1686
                        break;
1687
                    case 1:
1688
                        gen_op_fildl_ST0_A0();
1689
                        break;
1690
                    case 2:
1691
                        gen_op_fldl_ST0_A0();
1692
                        break;
1693
                    case 3:
1694
                    default:
1695
                        gen_op_fild_ST0_A0();
1696
                        break;
1697
                    }
1698
                    break;
1699
                default:
1700
                    switch(op >> 4) {
1701
                    case 0:
1702
                        gen_op_fsts_ST0_A0();
1703
                        break;
1704
                    case 1:
1705
                        gen_op_fistl_ST0_A0();
1706
                        break;
1707
                    case 2:
1708
                        gen_op_fstl_ST0_A0();
1709
                        break;
1710
                    case 3:
1711
                    default:
1712
                        gen_op_fist_ST0_A0();
1713
                        break;
1714
                    }
1715
                    if ((op & 7) == 3)
1716
                        gen_op_fpop();
1717
                    break;
1718
                }
1719
                break;
1720
#if 0
1721
            case 0x2f: /* fnstsw mem */
1722
                gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
1723
                gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
1724
                break;
1725

1726
            case 0x3c: /* fbld */
1727
            case 0x3e: /* fbstp */
1728
                error("float BCD not hanlded");
1729
                return -1;
1730
#endif
1731
            case 0x3d: /* fildll */
1732
                gen_op_fpush();
1733
                gen_op_fildll_ST0_A0();
1734
                break;
1735
            case 0x3f: /* fistpll */
1736
                gen_op_fistll_ST0_A0();
1737
                gen_op_fpop();
1738
                break;
1739
            default:
1740
                error("unhandled memory FP\n");
1741
                return -1;
1742
            }
1743
        } else {
1744
            /* register float ops */
1745
            opreg = rm;
1746

    
1747
            switch(op) {
1748
            case 0x08: /* fld sti */
1749
                gen_op_fpush();
1750
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
1751
                break;
1752
            case 0x09: /* fxchg sti */
1753
                gen_op_fxchg_ST0_STN((opreg + 1) & 7);
1754
                break;
1755
            case 0x0a: /* grp d9/2 */
1756
                switch(rm) {
1757
                case 0: /* fnop */
1758
                    break;
1759
                default:
1760
                    error("unhandled FP GRP d9/2\n");
1761
                    return -1;
1762
                }
1763
                break;
1764
            case 0x0c: /* grp d9/4 */
1765
                switch(rm) {
1766
                case 0: /* fchs */
1767
                    gen_op_fchs_ST0();
1768
                    break;
1769
                case 1: /* fabs */
1770
                    gen_op_fabs_ST0();
1771
                    break;
1772
                case 4: /* ftst */
1773
                    gen_op_fldz_FT0();
1774
                    gen_op_fcom_ST0_FT0();
1775
                    break;
1776
                case 5: /* fxam */
1777
                    gen_op_fxam_ST0();
1778
                    break;
1779
                default:
1780
                    return -1;
1781
                }
1782
                break;
1783
            case 0x0d: /* grp d9/5 */
1784
                {
1785
                    switch(rm) {
1786
                    case 0:
1787
                        gen_op_fld1_ST0();
1788
                        break;
1789
                    case 1:
1790
                        gen_op_fld2t_ST0();
1791
                        break;
1792
                    case 2:
1793
                        gen_op_fld2e_ST0();
1794
                        break;
1795
                    case 3:
1796
                        gen_op_fldpi_ST0();
1797
                        break;
1798
                    case 4:
1799
                        gen_op_fldlg2_ST0();
1800
                        break;
1801
                    case 5:
1802
                        gen_op_fldln2_ST0();
1803
                        break;
1804
                    case 6:
1805
                        gen_op_fldz_ST0();
1806
                        break;
1807
                    default:
1808
                        return -1;
1809
                    }
1810
                }
1811
                break;
1812
            case 0x0e: /* grp d9/6 */
1813
                switch(rm) {
1814
                case 0: /* f2xm1 */
1815
                    gen_op_f2xm1();
1816
                    break;
1817
                case 1: /* fyl2x */
1818
                    gen_op_fyl2x();
1819
                    break;
1820
                case 2: /* fptan */
1821
                    gen_op_fptan();
1822
                    break;
1823
                case 3: /* fpatan */
1824
                    gen_op_fpatan();
1825
                    break;
1826
                case 4: /* fxtract */
1827
                    gen_op_fxtract();
1828
                    break;
1829
                case 5: /* fprem1 */
1830
                    gen_op_fprem1();
1831
                    break;
1832
                case 6: /* fdecstp */
1833
                    gen_op_fdecstp();
1834
                    break;
1835
                default:
1836
                case 7: /* fincstp */
1837
                    gen_op_fincstp();
1838
                    break;
1839
                }
1840
                break;
1841
            case 0x0f: /* grp d9/7 */
1842
                switch(rm) {
1843
                case 0: /* fprem */
1844
                    gen_op_fprem();
1845
                    break;
1846
                case 1: /* fyl2xp1 */
1847
                    gen_op_fyl2xp1();
1848
                    break;
1849
                case 2: /* fsqrt */
1850
                    gen_op_fsqrt();
1851
                    break;
1852
                case 3: /* fsincos */
1853
                    gen_op_fsincos();
1854
                    break;
1855
                case 5: /* fscale */
1856
                    gen_op_fscale();
1857
                    break;
1858
                case 4: /* frndint */
1859
                    gen_op_frndint();
1860
                    break;
1861
                case 6: /* fsin */
1862
                    gen_op_fsin();
1863
                    break;
1864
                default:
1865
                case 7: /* fcos */
1866
                    gen_op_fcos();
1867
                    break;
1868
                }
1869
                break;
1870
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
1871
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
1872
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
1873
                {
1874
                    int op1;
1875
                    
1876
                    op1 = op & 7;
1877
                    if (op >= 0x20) {
1878
                        gen_op_fp_arith_STN_ST0[op1](opreg);
1879
                    } else {
1880
                        gen_op_fmov_FT0_STN(opreg);
1881
                        gen_op_fp_arith_ST0_FT0[op1]();
1882
                    }
1883
                    if (op >= 0x30)
1884
                        gen_op_fpop();
1885
                }
1886
                break;
1887
            case 0x02: /* fcom */
1888
                gen_op_fmov_FT0_STN(opreg);
1889
                gen_op_fcom_ST0_FT0();
1890
                break;
1891
            case 0x03: /* fcomp */
1892
                gen_op_fmov_FT0_STN(opreg);
1893
                gen_op_fcom_ST0_FT0();
1894
                gen_op_fpop();
1895
                break;
1896
            case 0x15: /* da/5 */
1897
                switch(rm) {
1898
                case 1: /* fucompp */
1899
                    gen_op_fmov_FT0_STN(1);
1900
                    gen_op_fcom_ST0_FT0();
1901
                    gen_op_fpop();
1902
                    gen_op_fpop();
1903
                    break;
1904
                default:
1905
                    return -1;
1906
                }
1907
                break;
1908
            case 0x2a: /* fst sti */
1909
                gen_op_fmov_STN_ST0(opreg);
1910
                break;
1911
            case 0x2b: /* fstp sti */
1912
                gen_op_fmov_STN_ST0(opreg);
1913
                gen_op_fpop();
1914
                break;
1915
            case 0x33: /* de/3 */
1916
                switch(rm) {
1917
                case 1: /* fcompp */
1918
                    gen_op_fmov_FT0_STN(1);
1919
                    gen_op_fcom_ST0_FT0();
1920
                    gen_op_fpop();
1921
                    gen_op_fpop();
1922
                    break;
1923
                default:
1924
                    return -1;
1925
                }
1926
                break;
1927
            case 0x3c: /* df/4 */
1928
                switch(rm) {
1929
#if 0
1930
                case 0:
1931
                    gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
1932
                    break;
1933
#endif
1934
                default:
1935
                    return -1;
1936
                }
1937
                break;
1938
            default:
1939
                error("unhandled FP\n");
1940
                return -1;
1941
            }
1942
        }
1943
        break;
1944
        /************************/
1945
        /* string ops */
1946
    case 0xa4: /* movsS */
1947
    case 0xa5:
1948
        if ((b & 1) == 0)
1949
            ot = OT_BYTE;
1950
        else
1951
            ot = dflag ? OT_LONG : OT_WORD;
1952
        if (prefixes & PREFIX_REPZ) {
1953
            gen_op_movs[3 + ot]();
1954
        } else {
1955
            gen_op_movs[ot]();
1956
        }
1957
        break;
1958
        
1959
    case 0xaa: /* stosS */
1960
    case 0xab:
1961
        if ((b & 1) == 0)
1962
            ot = OT_BYTE;
1963
        else
1964
            ot = dflag ? OT_LONG : OT_WORD;
1965
        if (prefixes & PREFIX_REPZ) {
1966
            gen_op_stos[3 + ot]();
1967
        } else {
1968
            gen_op_stos[ot]();
1969
        }
1970
        break;
1971
    case 0xac: /* lodsS */
1972
    case 0xad:
1973
        if ((b & 1) == 0)
1974
            ot = OT_BYTE;
1975
        else
1976
            ot = dflag ? OT_LONG : OT_WORD;
1977
        if (prefixes & PREFIX_REPZ) {
1978
            gen_op_lods[3 + ot]();
1979
        } else {
1980
            gen_op_lods[ot]();
1981
        }
1982
        break;
1983
    case 0xae: /* scasS */
1984
    case 0xaf:
1985
        if ((b & 1) == 0)
1986
            ot = OT_BYTE;
1987
        else
1988
            ot = dflag ? OT_LONG : OT_WORD;
1989
        if (prefixes & PREFIX_REPNZ) {
1990
            gen_op_scas[6 + ot]();
1991
        } else if (prefixes & PREFIX_REPZ) {
1992
            gen_op_scas[3 + ot]();
1993
        } else {
1994
            gen_op_scas[ot]();
1995
        }
1996
        break;
1997

    
1998
    case 0xa6: /* cmpsS */
1999
    case 0xa7:
2000
        if ((b & 1) == 0)
2001
            ot = OT_BYTE;
2002
        else
2003
            ot = dflag ? OT_LONG : OT_WORD;
2004
        if (prefixes & PREFIX_REPNZ) {
2005
            gen_op_cmps[6 + ot]();
2006
        } else if (prefixes & PREFIX_REPZ) {
2007
            gen_op_cmps[3 + ot]();
2008
        } else {
2009
            gen_op_cmps[ot]();
2010
        }
2011
        break;
2012
        
2013
        /************************/
2014
        /* port I/O */
2015
    case 0x6c: /* insS */
2016
    case 0x6d:
2017
        if ((b & 1) == 0)
2018
            ot = OT_BYTE;
2019
        else
2020
            ot = dflag ? OT_LONG : OT_WORD;
2021
        if (prefixes & PREFIX_REPZ) {
2022
            gen_op_ins[3 + ot]();
2023
        } else {
2024
            gen_op_ins[ot]();
2025
        }
2026
        break;
2027
    case 0x6e: /* outsS */
2028
    case 0x6f:
2029
        if ((b & 1) == 0)
2030
            ot = OT_BYTE;
2031
        else
2032
            ot = dflag ? OT_LONG : OT_WORD;
2033
        if (prefixes & PREFIX_REPZ) {
2034
            gen_op_outs[3 + ot]();
2035
        } else {
2036
            gen_op_outs[ot]();
2037
        }
2038
        break;
2039
    case 0xe4:
2040
    case 0xe5:
2041
        if ((b & 1) == 0)
2042
            ot = OT_BYTE;
2043
        else
2044
            ot = dflag ? OT_LONG : OT_WORD;
2045
        val = ldub(s->pc++);
2046
        gen_op_movl_T0_im(val);
2047
        gen_op_in[ot]();
2048
        gen_op_mov_reg_T1[ot][R_EAX]();
2049
        break;
2050
    case 0xe6:
2051
    case 0xe7:
2052
        if ((b & 1) == 0)
2053
            ot = OT_BYTE;
2054
        else
2055
            ot = dflag ? OT_LONG : OT_WORD;
2056
        val = ldub(s->pc++);
2057
        gen_op_movl_T0_im(val);
2058
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2059
        gen_op_out[ot]();
2060
        break;
2061
    case 0xec:
2062
    case 0xed:
2063
        if ((b & 1) == 0)
2064
            ot = OT_BYTE;
2065
        else
2066
            ot = dflag ? OT_LONG : OT_WORD;
2067
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2068
        gen_op_in[ot]();
2069
        gen_op_mov_reg_T1[ot][R_EAX]();
2070
        break;
2071
    case 0xee:
2072
    case 0xef:
2073
        if ((b & 1) == 0)
2074
            ot = OT_BYTE;
2075
        else
2076
            ot = dflag ? OT_LONG : OT_WORD;
2077
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2078
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2079
        gen_op_out[ot]();
2080
        break;
2081

    
2082
        /************************/
2083
        /* control */
2084
    case 0xc2: /* ret im */
2085
        /* XXX: handle stack pop ? */
2086
        val = ldsw(s->pc);
2087
        s->pc += 2;
2088
        gen_op_popl_T0();
2089
        gen_op_addl_ESP_im(val);
2090
        gen_op_jmp_T0();
2091
        *is_jmp_ptr = 1;
2092
        break;
2093
    case 0xc3: /* ret */
2094
        gen_op_popl_T0();
2095
        gen_op_jmp_T0();
2096
        *is_jmp_ptr = 1;
2097
        break;
2098
    case 0xe8: /* call */
2099
        val = insn_get(s, OT_LONG);
2100
        val += (long)s->pc;
2101
        gen_op_movl_T1_im((long)s->pc);
2102
        gen_op_pushl_T1();
2103
        gen_op_jmp_im(val);
2104
        *is_jmp_ptr = 1;
2105
        break;
2106
    case 0xe9: /* jmp */
2107
        val = insn_get(s, OT_LONG);
2108
        val += (long)s->pc;
2109
        gen_op_jmp_im(val);
2110
        *is_jmp_ptr = 1;
2111
        break;
2112
    case 0xeb: /* jmp Jb */
2113
        val = (int8_t)insn_get(s, OT_BYTE);
2114
        val += (long)s->pc;
2115
        gen_op_jmp_im(val);
2116
        *is_jmp_ptr = 1;
2117
        break;
2118
    case 0x70 ... 0x7f: /* jcc Jb */
2119
        val = (int8_t)insn_get(s, OT_BYTE);
2120
        val += (long)s->pc;
2121
        goto do_jcc;
2122
    case 0x180 ... 0x18f: /* jcc Jv */
2123
        if (dflag) {
2124
            val = insn_get(s, OT_LONG);
2125
        } else {
2126
            val = (int16_t)insn_get(s, OT_WORD); 
2127
        }
2128
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2129
    do_jcc:
2130
        gen_jcc(s, b, val);
2131
        *is_jmp_ptr = 1;
2132
        break;
2133

    
2134
    case 0x190 ... 0x19f:
2135
        modrm = ldub(s->pc++);
2136
        gen_setcc(s, b);
2137
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2138
        break;
2139

    
2140
        /************************/
2141
        /* flags */
2142
    case 0x9c: /* pushf */
2143
        gen_op_movl_T0_eflags();
2144
        gen_op_pushl_T0();
2145
        break;
2146
    case 0x9d: /* popf */
2147
        gen_op_popl_T0();
2148
        gen_op_movl_eflags_T0();
2149
        s->cc_op = CC_OP_EFLAGS;
2150
        break;
2151
    case 0x9e: /* sahf */
2152
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2153
        if (s->cc_op != CC_OP_DYNAMIC)
2154
            op_set_cc_op(s->cc_op);
2155
        gen_op_movb_eflags_T0();
2156
        s->cc_op = CC_OP_EFLAGS;
2157
        break;
2158
    case 0x9f: /* lahf */
2159
        if (s->cc_op != CC_OP_DYNAMIC)
2160
            op_set_cc_op(s->cc_op);
2161
        gen_op_movl_T0_eflags();
2162
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2163
        break;
2164
    case 0xf5: /* cmc */
2165
        if (s->cc_op != CC_OP_DYNAMIC)
2166
            op_set_cc_op(s->cc_op);
2167
        gen_op_cmc();
2168
        s->cc_op = CC_OP_EFLAGS;
2169
        break;
2170
    case 0xf8: /* clc */
2171
        if (s->cc_op != CC_OP_DYNAMIC)
2172
            op_set_cc_op(s->cc_op);
2173
        gen_op_clc();
2174
        s->cc_op = CC_OP_EFLAGS;
2175
        break;
2176
    case 0xf9: /* stc */
2177
        if (s->cc_op != CC_OP_DYNAMIC)
2178
            op_set_cc_op(s->cc_op);
2179
        gen_op_stc();
2180
        s->cc_op = CC_OP_EFLAGS;
2181
        break;
2182
    case 0xfc: /* cld */
2183
        gen_op_cld();
2184
        break;
2185
    case 0xfd: /* std */
2186
        gen_op_std();
2187
        break;
2188

    
2189
        /************************/
2190
        /* misc */
2191
    case 0x90: /* nop */
2192
        break;
2193
    case 0xcc: /* int3 */
2194
        gen_op_int3((long)pc_start);
2195
        *is_jmp_ptr = 1;
2196
        break;
2197
    case 0xcd: /* int N */
2198
        val = ldub(s->pc++);
2199
        /* XXX: currently we ignore the interrupt number */
2200
        gen_op_int_im((long)pc_start);
2201
        *is_jmp_ptr = 1;
2202
        break;
2203
    case 0xce: /* into */
2204
        if (s->cc_op != CC_OP_DYNAMIC)
2205
            gen_op_set_cc_op(s->cc_op);
2206
        gen_op_into((long)pc_start, (long)s->pc);
2207
        *is_jmp_ptr = 1;
2208
        break;
2209
#if 0
2210
    case 0x1a2: /* cpuid */
2211
        gen_insn0(OP_ASM);
2212
        break;
2213
#endif
2214
    default:
2215
        error("unknown opcode %x", b);
2216
        return -1;
2217
    }
2218
    return (long)s->pc;
2219
}
2220

    
2221
/* return the next pc */
2222
int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
2223
                     uint8_t *pc_start)
2224
{
2225
    DisasContext dc1, *dc = &dc1;
2226
    int is_jmp;
2227
    long ret;
2228
#ifdef DEBUG_DISAS
2229
    struct disassemble_info disasm_info;
2230
#endif
2231

    
2232
    dc->cc_op = CC_OP_DYNAMIC;
2233
    gen_code_ptr = gen_code_buf;
2234
    gen_start();
2235

    
2236
#ifdef DEBUG_DISAS
2237
    if (loglevel) {
2238
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2239
        disasm_info.buffer = pc_start;
2240
        disasm_info.buffer_vma = (unsigned long)pc_start;
2241
        disasm_info.buffer_length = 15;
2242
#if 0        
2243
        disasm_info.flavour = bfd_get_flavour (abfd);
2244
        disasm_info.arch = bfd_get_arch (abfd);
2245
        disasm_info.mach = bfd_get_mach (abfd);
2246
#endif
2247
#ifdef WORDS_BIGENDIAN
2248
        disasm_info.endian = BFD_ENDIAN_BIG;
2249
#else
2250
        disasm_info.endian = BFD_ENDIAN_LITTLE;
2251
#endif        
2252
        fprintf(logfile, "IN:\n");
2253
        fprintf(logfile, "0x%08lx:  ", (long)pc_start);
2254
        print_insn_i386((unsigned long)pc_start, &disasm_info);
2255
        fprintf(logfile, "\n\n");
2256
    }
2257
#endif
2258
    is_jmp = 0;
2259
    ret = disas_insn(dc, pc_start, &is_jmp);
2260
    if (ret == -1) 
2261
        error("unknown instruction at PC=0x%x", pc_start);
2262
    /* we must store the eflags state if it is not already done */
2263
    if (dc->cc_op != CC_OP_DYNAMIC)
2264
        gen_op_set_cc_op(dc->cc_op);
2265
    if (!is_jmp) {
2266
        /* we add an additionnal jmp to update the simulated PC */
2267
        gen_op_jmp_im(ret);
2268
    }
2269
    gen_end();
2270
    *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2271

    
2272
#ifdef DEBUG_DISAS
2273
    if (loglevel) {
2274
        uint8_t *pc;
2275
        int count;
2276

    
2277
        pc = gen_code_buf;
2278
        disasm_info.buffer = pc;
2279
        disasm_info.buffer_vma = (unsigned long)pc;
2280
        disasm_info.buffer_length = *gen_code_size_ptr;
2281
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2282
        while (pc < gen_code_ptr) {
2283
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2284
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2285
            fprintf(logfile, "\n");
2286
            pc += count;
2287
        }
2288
        fprintf(logfile, "\n");
2289
    }
2290
#endif
2291
    return 0;
2292
}
2293

    
2294
CPUX86State *cpu_x86_init(void)
2295
{
2296
    CPUX86State *env;
2297
    int i;
2298

    
2299
    env = malloc(sizeof(CPUX86State));
2300
    if (!env)
2301
        return NULL;
2302
    memset(env, 0, sizeof(CPUX86State));
2303
    /* basic FPU init */
2304
    for(i = 0;i < 8; i++)
2305
        env->fptags[i] = 1;
2306
    env->fpuc = 0x37f;
2307
    /* flags setup */
2308
    env->cc_op = CC_OP_EFLAGS;
2309
    env->df = 1;
2310
    return env;
2311
}
2312

    
2313
void cpu_x86_close(CPUX86State *env)
2314
{
2315
    free(env);
2316
}