Statistics
| Branch: | Revision:

root / translate-i386.c @ d57c4e01

History | View | Annotate | Download (64.9 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
    fprintf(stderr, "\n");
31
    vfprintf(stderr, fmt, ap);
32
    fprintf(stderr, "\n");
33
    va_end(ap);
34
    exit(1);
35
}
36

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

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

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

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

    
83
#include "op-i386.h"
84

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

    
93
enum {
94
    /* I386 int registers */
95
    OR_EAX,   /* MUST be even numbered */
96
    OR_ECX,
97
    OR_EDX,
98
    OR_EBX,
99
    OR_ESP,
100
    OR_EBP,
101
    OR_ESI,
102
    OR_EDI,
103
    OR_TMP0,    /* temporary operand register */
104
    OR_TMP1,
105
    OR_A0, /* temporary register used when doing address evaluation */
106
    OR_ZERO, /* fixed zero register */
107
    NB_OREGS,
108
};
109

    
110
typedef void (GenOpFunc)(void);
111
typedef void (GenOpFunc1)(long);
112
typedef void (GenOpFunc2)(long, long);
113
                    
114
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
115
    [OT_BYTE] = {
116
        gen_op_movb_EAX_T0,
117
        gen_op_movb_ECX_T0,
118
        gen_op_movb_EDX_T0,
119
        gen_op_movb_EBX_T0,
120
        gen_op_movh_EAX_T0,
121
        gen_op_movh_ECX_T0,
122
        gen_op_movh_EDX_T0,
123
        gen_op_movh_EBX_T0,
124
    },
125
    [OT_WORD] = {
126
        gen_op_movw_EAX_T0,
127
        gen_op_movw_ECX_T0,
128
        gen_op_movw_EDX_T0,
129
        gen_op_movw_EBX_T0,
130
        gen_op_movw_ESP_T0,
131
        gen_op_movw_EBP_T0,
132
        gen_op_movw_ESI_T0,
133
        gen_op_movw_EDI_T0,
134
    },
135
    [OT_LONG] = {
136
        gen_op_movl_EAX_T0,
137
        gen_op_movl_ECX_T0,
138
        gen_op_movl_EDX_T0,
139
        gen_op_movl_EBX_T0,
140
        gen_op_movl_ESP_T0,
141
        gen_op_movl_EBP_T0,
142
        gen_op_movl_ESI_T0,
143
        gen_op_movl_EDI_T0,
144
    },
145
};
146

    
147
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
148
    [OT_BYTE] = {
149
        gen_op_movb_EAX_T1,
150
        gen_op_movb_ECX_T1,
151
        gen_op_movb_EDX_T1,
152
        gen_op_movb_EBX_T1,
153
        gen_op_movh_EAX_T1,
154
        gen_op_movh_ECX_T1,
155
        gen_op_movh_EDX_T1,
156
        gen_op_movh_EBX_T1,
157
    },
158
    [OT_WORD] = {
159
        gen_op_movw_EAX_T1,
160
        gen_op_movw_ECX_T1,
161
        gen_op_movw_EDX_T1,
162
        gen_op_movw_EBX_T1,
163
        gen_op_movw_ESP_T1,
164
        gen_op_movw_EBP_T1,
165
        gen_op_movw_ESI_T1,
166
        gen_op_movw_EDI_T1,
167
    },
168
    [OT_LONG] = {
169
        gen_op_movl_EAX_T1,
170
        gen_op_movl_ECX_T1,
171
        gen_op_movl_EDX_T1,
172
        gen_op_movl_EBX_T1,
173
        gen_op_movl_ESP_T1,
174
        gen_op_movl_EBP_T1,
175
        gen_op_movl_ESI_T1,
176
        gen_op_movl_EDI_T1,
177
    },
178
};
179

    
180
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
181
    [0] = {
182
        gen_op_movw_EAX_A0,
183
        gen_op_movw_ECX_A0,
184
        gen_op_movw_EDX_A0,
185
        gen_op_movw_EBX_A0,
186
        gen_op_movw_ESP_A0,
187
        gen_op_movw_EBP_A0,
188
        gen_op_movw_ESI_A0,
189
        gen_op_movw_EDI_A0,
190
    },
191
    [1] = {
192
        gen_op_movl_EAX_A0,
193
        gen_op_movl_ECX_A0,
194
        gen_op_movl_EDX_A0,
195
        gen_op_movl_EBX_A0,
196
        gen_op_movl_ESP_A0,
197
        gen_op_movl_EBP_A0,
198
        gen_op_movl_ESI_A0,
199
        gen_op_movl_EDI_A0,
200
    },
201
};
202

    
203
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
204
{
205
    [OT_BYTE] = {
206
        {
207
            gen_op_movl_T0_EAX,
208
            gen_op_movl_T0_ECX,
209
            gen_op_movl_T0_EDX,
210
            gen_op_movl_T0_EBX,
211
            gen_op_movh_T0_EAX,
212
            gen_op_movh_T0_ECX,
213
            gen_op_movh_T0_EDX,
214
            gen_op_movh_T0_EBX,
215
        },
216
        {
217
            gen_op_movl_T1_EAX,
218
            gen_op_movl_T1_ECX,
219
            gen_op_movl_T1_EDX,
220
            gen_op_movl_T1_EBX,
221
            gen_op_movh_T1_EAX,
222
            gen_op_movh_T1_ECX,
223
            gen_op_movh_T1_EDX,
224
            gen_op_movh_T1_EBX,
225
        },
226
    },
227
    [OT_WORD] = {
228
        {
229
            gen_op_movl_T0_EAX,
230
            gen_op_movl_T0_ECX,
231
            gen_op_movl_T0_EDX,
232
            gen_op_movl_T0_EBX,
233
            gen_op_movl_T0_ESP,
234
            gen_op_movl_T0_EBP,
235
            gen_op_movl_T0_ESI,
236
            gen_op_movl_T0_EDI,
237
        },
238
        {
239
            gen_op_movl_T1_EAX,
240
            gen_op_movl_T1_ECX,
241
            gen_op_movl_T1_EDX,
242
            gen_op_movl_T1_EBX,
243
            gen_op_movl_T1_ESP,
244
            gen_op_movl_T1_EBP,
245
            gen_op_movl_T1_ESI,
246
            gen_op_movl_T1_EDI,
247
        },
248
    },
249
    [OT_LONG] = {
250
        {
251
            gen_op_movl_T0_EAX,
252
            gen_op_movl_T0_ECX,
253
            gen_op_movl_T0_EDX,
254
            gen_op_movl_T0_EBX,
255
            gen_op_movl_T0_ESP,
256
            gen_op_movl_T0_EBP,
257
            gen_op_movl_T0_ESI,
258
            gen_op_movl_T0_EDI,
259
        },
260
        {
261
            gen_op_movl_T1_EAX,
262
            gen_op_movl_T1_ECX,
263
            gen_op_movl_T1_EDX,
264
            gen_op_movl_T1_EBX,
265
            gen_op_movl_T1_ESP,
266
            gen_op_movl_T1_EBP,
267
            gen_op_movl_T1_ESI,
268
            gen_op_movl_T1_EDI,
269
        },
270
    },
271
};
272

    
273
static GenOpFunc *gen_op_movl_A0_reg[8] = {
274
    gen_op_movl_A0_EAX,
275
    gen_op_movl_A0_ECX,
276
    gen_op_movl_A0_EDX,
277
    gen_op_movl_A0_EBX,
278
    gen_op_movl_A0_ESP,
279
    gen_op_movl_A0_EBP,
280
    gen_op_movl_A0_ESI,
281
    gen_op_movl_A0_EDI,
282
};
283

    
284
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
285
    [0] = {
286
        gen_op_addl_A0_EAX,
287
        gen_op_addl_A0_ECX,
288
        gen_op_addl_A0_EDX,
289
        gen_op_addl_A0_EBX,
290
        gen_op_addl_A0_ESP,
291
        gen_op_addl_A0_EBP,
292
        gen_op_addl_A0_ESI,
293
        gen_op_addl_A0_EDI,
294
    },
295
    [1] = {
296
        gen_op_addl_A0_EAX_s1,
297
        gen_op_addl_A0_ECX_s1,
298
        gen_op_addl_A0_EDX_s1,
299
        gen_op_addl_A0_EBX_s1,
300
        gen_op_addl_A0_ESP_s1,
301
        gen_op_addl_A0_EBP_s1,
302
        gen_op_addl_A0_ESI_s1,
303
        gen_op_addl_A0_EDI_s1,
304
    },
305
    [2] = {
306
        gen_op_addl_A0_EAX_s2,
307
        gen_op_addl_A0_ECX_s2,
308
        gen_op_addl_A0_EDX_s2,
309
        gen_op_addl_A0_EBX_s2,
310
        gen_op_addl_A0_ESP_s2,
311
        gen_op_addl_A0_EBP_s2,
312
        gen_op_addl_A0_ESI_s2,
313
        gen_op_addl_A0_EDI_s2,
314
    },
315
    [3] = {
316
        gen_op_addl_A0_EAX_s3,
317
        gen_op_addl_A0_ECX_s3,
318
        gen_op_addl_A0_EDX_s3,
319
        gen_op_addl_A0_EBX_s3,
320
        gen_op_addl_A0_ESP_s3,
321
        gen_op_addl_A0_EBP_s3,
322
        gen_op_addl_A0_ESI_s3,
323
        gen_op_addl_A0_EDI_s3,
324
    },
325
};
326

    
327
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
328
    gen_op_addl_T0_T1_cc,
329
    gen_op_orl_T0_T1_cc,
330
    NULL,
331
    NULL,
332
    gen_op_andl_T0_T1_cc,
333
    gen_op_subl_T0_T1_cc,
334
    gen_op_xorl_T0_T1_cc,
335
    gen_op_cmpl_T0_T1_cc,
336
};
337

    
338
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
339
    [OT_BYTE] = {
340
        gen_op_adcb_T0_T1_cc,
341
        gen_op_sbbb_T0_T1_cc,
342
    },
343
    [OT_WORD] = {
344
        gen_op_adcw_T0_T1_cc,
345
        gen_op_sbbw_T0_T1_cc,
346
    },
347
    [OT_LONG] = {
348
        gen_op_adcl_T0_T1_cc,
349
        gen_op_sbbl_T0_T1_cc,
350
    },
351
};
352

    
353
static const int cc_op_arithb[8] = {
354
    CC_OP_ADDB,
355
    CC_OP_LOGICB,
356
    CC_OP_ADDB,
357
    CC_OP_SUBB,
358
    CC_OP_LOGICB,
359
    CC_OP_SUBB,
360
    CC_OP_LOGICB,
361
    CC_OP_SUBB,
362
};
363

    
364
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
365
    [OT_BYTE] = {
366
        gen_op_rolb_T0_T1_cc,
367
        gen_op_rorb_T0_T1_cc,
368
        gen_op_rclb_T0_T1_cc,
369
        gen_op_rcrb_T0_T1_cc,
370
        gen_op_shlb_T0_T1_cc,
371
        gen_op_shrb_T0_T1_cc,
372
        gen_op_shlb_T0_T1_cc,
373
        gen_op_sarb_T0_T1_cc,
374
    },
375
    [OT_WORD] = {
376
        gen_op_rolw_T0_T1_cc,
377
        gen_op_rorw_T0_T1_cc,
378
        gen_op_rclw_T0_T1_cc,
379
        gen_op_rcrw_T0_T1_cc,
380
        gen_op_shlw_T0_T1_cc,
381
        gen_op_shrw_T0_T1_cc,
382
        gen_op_shlw_T0_T1_cc,
383
        gen_op_sarw_T0_T1_cc,
384
    },
385
    [OT_LONG] = {
386
        gen_op_roll_T0_T1_cc,
387
        gen_op_rorl_T0_T1_cc,
388
        gen_op_rcll_T0_T1_cc,
389
        gen_op_rcrl_T0_T1_cc,
390
        gen_op_shll_T0_T1_cc,
391
        gen_op_shrl_T0_T1_cc,
392
        gen_op_shll_T0_T1_cc,
393
        gen_op_sarl_T0_T1_cc,
394
    },
395
};
396

    
397
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
398
    [0] = {
399
        gen_op_shldw_T0_T1_im_cc,
400
        gen_op_shrdw_T0_T1_im_cc,
401
    },
402
    [1] = {
403
        gen_op_shldl_T0_T1_im_cc,
404
        gen_op_shrdl_T0_T1_im_cc,
405
    },
406
};
407

    
408
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
409
    [0] = {
410
        gen_op_shldw_T0_T1_ECX_cc,
411
        gen_op_shrdw_T0_T1_ECX_cc,
412
    },
413
    [1] = {
414
        gen_op_shldl_T0_T1_ECX_cc,
415
        gen_op_shrdl_T0_T1_ECX_cc,
416
    },
417
};
418

    
419
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
420
    [0] = {
421
        gen_op_btw_T0_T1_cc,
422
        gen_op_btsw_T0_T1_cc,
423
        gen_op_btrw_T0_T1_cc,
424
        gen_op_btcw_T0_T1_cc,
425
    },
426
    [1] = {
427
        gen_op_btl_T0_T1_cc,
428
        gen_op_btsl_T0_T1_cc,
429
        gen_op_btrl_T0_T1_cc,
430
        gen_op_btcl_T0_T1_cc,
431
    },
432
};
433

    
434
static GenOpFunc *gen_op_lds_T0_A0[3] = {
435
    gen_op_ldsb_T0_A0,
436
    gen_op_ldsw_T0_A0,
437
};
438

    
439
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
440
    gen_op_ldub_T0_A0,
441
    gen_op_lduw_T0_A0,
442
};
443

    
444
/* sign does not matter */
445
static GenOpFunc *gen_op_ld_T0_A0[3] = {
446
    gen_op_ldub_T0_A0,
447
    gen_op_lduw_T0_A0,
448
    gen_op_ldl_T0_A0,
449
};
450

    
451
static GenOpFunc *gen_op_ld_T1_A0[3] = {
452
    gen_op_ldub_T1_A0,
453
    gen_op_lduw_T1_A0,
454
    gen_op_ldl_T1_A0,
455
};
456

    
457
static GenOpFunc *gen_op_st_T0_A0[3] = {
458
    gen_op_stb_T0_A0,
459
    gen_op_stw_T0_A0,
460
    gen_op_stl_T0_A0,
461
};
462

    
463
static GenOpFunc *gen_op_movs[6] = {
464
    gen_op_movsb,
465
    gen_op_movsw,
466
    gen_op_movsl,
467
    gen_op_rep_movsb,
468
    gen_op_rep_movsw,
469
    gen_op_rep_movsl,
470
};
471

    
472
static GenOpFunc *gen_op_stos[6] = {
473
    gen_op_stosb,
474
    gen_op_stosw,
475
    gen_op_stosl,
476
    gen_op_rep_stosb,
477
    gen_op_rep_stosw,
478
    gen_op_rep_stosl,
479
};
480

    
481
static GenOpFunc *gen_op_lods[6] = {
482
    gen_op_lodsb,
483
    gen_op_lodsw,
484
    gen_op_lodsl,
485
    gen_op_rep_lodsb,
486
    gen_op_rep_lodsw,
487
    gen_op_rep_lodsl,
488
};
489

    
490
static GenOpFunc *gen_op_scas[9] = {
491
    gen_op_scasb,
492
    gen_op_scasw,
493
    gen_op_scasl,
494
    gen_op_repz_scasb,
495
    gen_op_repz_scasw,
496
    gen_op_repz_scasl,
497
    gen_op_repnz_scasb,
498
    gen_op_repnz_scasw,
499
    gen_op_repnz_scasl,
500
};
501

    
502
static GenOpFunc *gen_op_cmps[9] = {
503
    gen_op_cmpsb,
504
    gen_op_cmpsw,
505
    gen_op_cmpsl,
506
    gen_op_repz_cmpsb,
507
    gen_op_repz_cmpsw,
508
    gen_op_repz_cmpsl,
509
    gen_op_repnz_cmpsb,
510
    gen_op_repnz_cmpsw,
511
    gen_op_repnz_cmpsl,
512
};
513

    
514
static GenOpFunc *gen_op_ins[6] = {
515
    gen_op_insb,
516
    gen_op_insw,
517
    gen_op_insl,
518
    gen_op_rep_insb,
519
    gen_op_rep_insw,
520
    gen_op_rep_insl,
521
};
522

    
523

    
524
static GenOpFunc *gen_op_outs[6] = {
525
    gen_op_outsb,
526
    gen_op_outsw,
527
    gen_op_outsl,
528
    gen_op_rep_outsb,
529
    gen_op_rep_outsw,
530
    gen_op_rep_outsl,
531
};
532

    
533
static GenOpFunc *gen_op_in[3] = {
534
    gen_op_inb_T0_T1,
535
    gen_op_inw_T0_T1,
536
    gen_op_inl_T0_T1,
537
};
538

    
539
static GenOpFunc *gen_op_out[3] = {
540
    gen_op_outb_T0_T1,
541
    gen_op_outw_T0_T1,
542
    gen_op_outl_T0_T1,
543
};
544

    
545
enum {
546
    JCC_O,
547
    JCC_B,
548
    JCC_Z,
549
    JCC_BE,
550
    JCC_S,
551
    JCC_P,
552
    JCC_L,
553
    JCC_LE,
554
};
555

    
556
static GenOpFunc2 *gen_jcc_slow[8] = {
557
    gen_op_jo_cc,
558
    gen_op_jb_cc,
559
    gen_op_jz_cc,
560
    gen_op_jbe_cc,
561
    gen_op_js_cc,
562
    gen_op_jp_cc,
563
    gen_op_jl_cc,
564
    gen_op_jle_cc,
565
};
566
    
567
static GenOpFunc2 *gen_jcc_sub[3][8] = {
568
    [OT_BYTE] = {
569
        NULL,
570
        gen_op_jb_subb,
571
        gen_op_jz_subb,
572
        gen_op_jbe_subb,
573
        gen_op_js_subb,
574
        NULL,
575
        gen_op_jl_subb,
576
        gen_op_jle_subb,
577
    },
578
    [OT_WORD] = {
579
        NULL,
580
        gen_op_jb_subw,
581
        gen_op_jz_subw,
582
        gen_op_jbe_subw,
583
        gen_op_js_subw,
584
        NULL,
585
        gen_op_jl_subw,
586
        gen_op_jle_subw,
587
    },
588
    [OT_LONG] = {
589
        NULL,
590
        gen_op_jb_subl,
591
        gen_op_jz_subl,
592
        gen_op_jbe_subl,
593
        gen_op_js_subl,
594
        NULL,
595
        gen_op_jl_subl,
596
        gen_op_jle_subl,
597
    },
598
};
599

    
600
static GenOpFunc *gen_setcc_slow[8] = {
601
    gen_op_seto_T0_cc,
602
    gen_op_setb_T0_cc,
603
    gen_op_setz_T0_cc,
604
    gen_op_setbe_T0_cc,
605
    gen_op_sets_T0_cc,
606
    gen_op_setp_T0_cc,
607
    gen_op_setl_T0_cc,
608
    gen_op_setle_T0_cc,
609
};
610

    
611
static GenOpFunc *gen_setcc_sub[3][8] = {
612
    [OT_BYTE] = {
613
        NULL,
614
        gen_op_setb_T0_subb,
615
        gen_op_setz_T0_subb,
616
        gen_op_setbe_T0_subb,
617
        gen_op_sets_T0_subb,
618
        NULL,
619
        gen_op_setl_T0_subb,
620
        gen_op_setle_T0_subb,
621
    },
622
    [OT_WORD] = {
623
        NULL,
624
        gen_op_setb_T0_subw,
625
        gen_op_setz_T0_subw,
626
        gen_op_setbe_T0_subw,
627
        gen_op_sets_T0_subw,
628
        NULL,
629
        gen_op_setl_T0_subw,
630
        gen_op_setle_T0_subw,
631
    },
632
    [OT_LONG] = {
633
        NULL,
634
        gen_op_setb_T0_subl,
635
        gen_op_setz_T0_subl,
636
        gen_op_setbe_T0_subl,
637
        gen_op_sets_T0_subl,
638
        NULL,
639
        gen_op_setl_T0_subl,
640
        gen_op_setle_T0_subl,
641
    },
642
};
643

    
644
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
645
    gen_op_fadd_ST0_FT0,
646
    gen_op_fmul_ST0_FT0,
647
    gen_op_fcom_ST0_FT0,
648
    gen_op_fcom_ST0_FT0,
649
    gen_op_fsub_ST0_FT0,
650
    gen_op_fsubr_ST0_FT0,
651
    gen_op_fdiv_ST0_FT0,
652
    gen_op_fdivr_ST0_FT0,
653
};
654

    
655
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
656
    gen_op_fadd_STN_ST0,
657
    gen_op_fmul_STN_ST0,
658
    NULL,
659
    NULL,
660
    gen_op_fsub_STN_ST0,
661
    gen_op_fsubr_STN_ST0,
662
    gen_op_fdiv_STN_ST0,
663
    gen_op_fdivr_STN_ST0,
664
};
665

    
666
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
667
{
668
    if (d != OR_TMP0)
669
        gen_op_mov_TN_reg[ot][0][d]();
670
    if (s != OR_TMP1)
671
        gen_op_mov_TN_reg[ot][1][s]();
672
    if (op == OP_ADCL || op == OP_SBBL) {
673
        if (s1->cc_op != CC_OP_DYNAMIC)
674
            gen_op_set_cc_op(s1->cc_op);
675
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
676
        s1->cc_op = CC_OP_DYNAMIC;
677
    } else {
678
        gen_op_arith_T0_T1_cc[op]();
679
        s1->cc_op = cc_op_arithb[op] + ot;
680
    }
681
    if (d != OR_TMP0 && op != OP_CMPL)
682
        gen_op_mov_reg_T0[ot][d]();
683
}
684

    
685
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
686
{
687
    gen_op_movl_T1_im(c);
688
    gen_op(s1, op, ot, d, OR_TMP1);
689
}
690

    
691
static void gen_inc(DisasContext *s1, int ot, int d, int c)
692
{
693
    if (d != OR_TMP0)
694
        gen_op_mov_TN_reg[ot][0][d]();
695
    if (s1->cc_op != CC_OP_DYNAMIC)
696
        gen_op_set_cc_op(s1->cc_op);
697
    if (c > 0) {
698
        gen_op_incl_T0_cc();
699
        s1->cc_op = CC_OP_INCB + ot;
700
    } else {
701
        gen_op_decl_T0_cc();
702
        s1->cc_op = CC_OP_DECB + ot;
703
    }
704
    if (d != OR_TMP0)
705
        gen_op_mov_reg_T0[ot][d]();
706
}
707

    
708
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
709
{
710
    if (d != OR_TMP0)
711
        gen_op_mov_TN_reg[ot][0][d]();
712
    if (s != OR_TMP1)
713
        gen_op_mov_TN_reg[ot][1][s]();
714
    /* for zero counts, flags are not updated, so must do it dynamically */
715
    if (s1->cc_op != CC_OP_DYNAMIC)
716
        gen_op_set_cc_op(s1->cc_op);
717

    
718
    gen_op_shift_T0_T1_cc[ot][op]();
719

    
720
    if (d != OR_TMP0)
721
        gen_op_mov_reg_T0[ot][d]();
722
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
723
}
724

    
725
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
726
{
727
    /* currently not optimized */
728
    gen_op_movl_T1_im(c);
729
    gen_shift(s1, op, ot, d, OR_TMP1);
730
}
731

    
732
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
733
{
734
    int havesib;
735
    int havebase;
736
    int base, disp;
737
    int index = 0;
738
    int scale = 0;
739
    int reg1, reg2, opreg;
740
    int mod, rm, code;
741

    
742
    mod = (modrm >> 6) & 3;
743
    rm = modrm & 7;
744

    
745
    if (s->aflag) {
746

    
747
        havesib = 0;
748
        havebase = 1;
749
        base = rm;
750
        
751
        if (base == 4) {
752
            havesib = 1;
753
            code = ldub(s->pc++);
754
            scale = (code >> 6) & 3;
755
            index = (code >> 3) & 7;
756
            base = code & 7;
757
        }
758

    
759
        switch (mod) {
760
        case 0:
761
            if (base == 5) {
762
                havebase = 0;
763
                disp = ldl(s->pc);
764
                s->pc += 4;
765
            } else {
766
                disp = 0;
767
            }
768
            break;
769
        case 1:
770
            disp = (int8_t)ldub(s->pc++);
771
            break;
772
        default:
773
        case 2:
774
            disp = ldl(s->pc);
775
            s->pc += 4;
776
            break;
777
        }
778

    
779
        reg1 = OR_ZERO;
780
        reg2 = OR_ZERO;
781
          
782
        if (havebase || (havesib && (index != 4 || scale != 0))) {
783
            if (havebase)
784
                reg1 = OR_EAX + base;
785
            if (havesib && index != 4) {
786
                if (havebase)
787
                    reg2 = index + OR_EAX;
788
                else
789
                    reg1 = index + OR_EAX;
790
            }
791
        }
792
        /* XXX: disp only ? */
793
        if (reg2 == OR_ZERO) {
794
            /* op: disp + (reg1 << scale) */
795
            if (reg1 == OR_ZERO) {
796
                gen_op_movl_A0_im(disp);
797
            } else if (scale == 0 && disp == 0) {
798
                gen_op_movl_A0_reg[reg1]();
799
            } else {
800
                gen_op_movl_A0_im(disp);
801
                gen_op_addl_A0_reg_sN[scale][reg1]();
802
            }
803
        } else {
804
            /* op: disp + reg1 + (reg2 << scale) */
805
            if (disp != 0) {
806
                gen_op_movl_A0_im(disp);
807
                gen_op_addl_A0_reg_sN[0][reg1]();
808
            } else {
809
                gen_op_movl_A0_reg[reg1]();
810
            }
811
            gen_op_addl_A0_reg_sN[scale][reg2]();
812
        }
813
    } else {
814
        switch (mod) {
815
        case 0:
816
            if (rm == 6) {
817
                disp = lduw(s->pc);
818
                s->pc += 2;
819
                gen_op_movl_A0_im(disp);
820
                goto no_rm;
821
            } else {
822
                disp = 0;
823
            }
824
            break;
825
        case 1:
826
            disp = (int8_t)ldub(s->pc++);
827
            break;
828
        default:
829
        case 2:
830
            disp = lduw(s->pc);
831
            s->pc += 2;
832
            break;
833
        }
834
        switch(rm) {
835
        case 0:
836
            gen_op_movl_A0_reg[R_EBX]();
837
            gen_op_addl_A0_reg_sN[0][R_ESI]();
838
            break;
839
        case 1:
840
            gen_op_movl_A0_reg[R_EBX]();
841
            gen_op_addl_A0_reg_sN[0][R_EDI]();
842
            break;
843
        case 2:
844
            gen_op_movl_A0_reg[R_EBP]();
845
            gen_op_addl_A0_reg_sN[0][R_ESI]();
846
            break;
847
        case 3:
848
            gen_op_movl_A0_reg[R_EBP]();
849
            gen_op_addl_A0_reg_sN[0][R_EDI]();
850
            break;
851
        case 4:
852
            gen_op_movl_A0_reg[R_ESI]();
853
            break;
854
        case 5:
855
            gen_op_movl_A0_reg[R_EDI]();
856
            break;
857
        case 6:
858
            gen_op_movl_A0_reg[R_EBP]();
859
            break;
860
        default:
861
        case 7:
862
            gen_op_movl_A0_reg[R_EBX]();
863
            break;
864
        }
865
        if (disp != 0)
866
            gen_op_addl_A0_im(disp);
867
        gen_op_andl_A0_ffff();
868
    no_rm: ;
869
    }
870
    opreg = OR_A0;
871
    disp = 0;
872
    *reg_ptr = opreg;
873
    *offset_ptr = disp;
874
}
875

    
876
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
877
   OR_TMP0 */
878
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
879
{
880
    int mod, rm, opreg, disp;
881

    
882
    mod = (modrm >> 6) & 3;
883
    rm = modrm & 7;
884
    if (mod == 3) {
885
        if (is_store) {
886
            if (reg != OR_TMP0)
887
                gen_op_mov_TN_reg[ot][0][reg]();
888
            gen_op_mov_reg_T0[ot][rm]();
889
        } else {
890
            gen_op_mov_TN_reg[ot][0][rm]();
891
            if (reg != OR_TMP0)
892
                gen_op_mov_reg_T0[ot][reg]();
893
        }
894
    } else {
895
        gen_lea_modrm(s, modrm, &opreg, &disp);
896
        if (is_store) {
897
            if (reg != OR_TMP0)
898
                gen_op_mov_TN_reg[ot][0][reg]();
899
            gen_op_st_T0_A0[ot]();
900
        } else {
901
            gen_op_ld_T0_A0[ot]();
902
            if (reg != OR_TMP0)
903
                gen_op_mov_reg_T0[ot][reg]();
904
        }
905
    }
906
}
907

    
908
static inline uint32_t insn_get(DisasContext *s, int ot)
909
{
910
    uint32_t ret;
911

    
912
    switch(ot) {
913
    case OT_BYTE:
914
        ret = ldub(s->pc);
915
        s->pc++;
916
        break;
917
    case OT_WORD:
918
        ret = lduw(s->pc);
919
        s->pc += 2;
920
        break;
921
    default:
922
    case OT_LONG:
923
        ret = ldl(s->pc);
924
        s->pc += 4;
925
        break;
926
    }
927
    return ret;
928
}
929

    
930
static void gen_jcc(DisasContext *s, int b, int val)
931
{
932
    int inv, jcc_op;
933
    GenOpFunc2 *func;
934

    
935
    inv = b & 1;
936
    jcc_op = (b >> 1) & 7;
937
    switch(s->cc_op) {
938
        /* we optimize the cmp/jcc case */
939
    case CC_OP_SUBB:
940
    case CC_OP_SUBW:
941
    case CC_OP_SUBL:
942
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
943
        if (!func)
944
            goto slow_jcc;
945
        break;
946
        
947
        /* some jumps are easy to compute */
948
    case CC_OP_ADDB:
949
    case CC_OP_ADDW:
950
    case CC_OP_ADDL:
951
    case CC_OP_ADCB:
952
    case CC_OP_ADCW:
953
    case CC_OP_ADCL:
954
    case CC_OP_SBBB:
955
    case CC_OP_SBBW:
956
    case CC_OP_SBBL:
957
    case CC_OP_LOGICB:
958
    case CC_OP_LOGICW:
959
    case CC_OP_LOGICL:
960
    case CC_OP_INCB:
961
    case CC_OP_INCW:
962
    case CC_OP_INCL:
963
    case CC_OP_DECB:
964
    case CC_OP_DECW:
965
    case CC_OP_DECL:
966
    case CC_OP_SHLB:
967
    case CC_OP_SHLW:
968
    case CC_OP_SHLL:
969
    case CC_OP_SARB:
970
    case CC_OP_SARW:
971
    case CC_OP_SARL:
972
        switch(jcc_op) {
973
        case JCC_Z:
974
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
975
            break;
976
        case JCC_S:
977
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
978
            break;
979
        default:
980
            goto slow_jcc;
981
        }
982
        break;
983
    default:
984
    slow_jcc:
985
        if (s->cc_op != CC_OP_DYNAMIC)
986
            op_set_cc_op(s->cc_op);
987
        func = gen_jcc_slow[jcc_op];
988
        break;
989
    }
990
    if (!inv) {
991
        func(val, (long)s->pc);
992
    } else {
993
        func((long)s->pc, val);
994
    }
995
}
996

    
997
static void gen_setcc(DisasContext *s, int b)
998
{
999
    int inv, jcc_op;
1000
    GenOpFunc *func;
1001

    
1002
    inv = b & 1;
1003
    jcc_op = (b >> 1) & 7;
1004
    switch(s->cc_op) {
1005
        /* we optimize the cmp/jcc case */
1006
    case CC_OP_SUBB:
1007
    case CC_OP_SUBW:
1008
    case CC_OP_SUBL:
1009
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1010
        if (!func)
1011
            goto slow_jcc;
1012
        break;
1013
        
1014
        /* some jumps are easy to compute */
1015
    case CC_OP_ADDB:
1016
    case CC_OP_ADDW:
1017
    case CC_OP_ADDL:
1018
    case CC_OP_LOGICB:
1019
    case CC_OP_LOGICW:
1020
    case CC_OP_LOGICL:
1021
    case CC_OP_INCB:
1022
    case CC_OP_INCW:
1023
    case CC_OP_INCL:
1024
    case CC_OP_DECB:
1025
    case CC_OP_DECW:
1026
    case CC_OP_DECL:
1027
    case CC_OP_SHLB:
1028
    case CC_OP_SHLW:
1029
    case CC_OP_SHLL:
1030
        switch(jcc_op) {
1031
        case JCC_Z:
1032
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
1033
            break;
1034
        case JCC_S:
1035
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
1036
            break;
1037
        default:
1038
            goto slow_jcc;
1039
        }
1040
        break;
1041
    default:
1042
    slow_jcc:
1043
        if (s->cc_op != CC_OP_DYNAMIC)
1044
            op_set_cc_op(s->cc_op);
1045
        func = gen_setcc_slow[jcc_op];
1046
        break;
1047
    }
1048
    func();
1049
    if (inv) {
1050
        gen_op_xor_T0_1();
1051
    }
1052
}
1053

    
1054
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1055
   is set to true if the instruction sets the PC (last instruction of
1056
   a basic block) */
1057
long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1058
{
1059
    int b, prefixes, aflag, dflag;
1060
    int shift, ot;
1061
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1062

    
1063
    s->pc = pc_start;
1064
    prefixes = 0;
1065
    aflag = 1;
1066
    dflag = 1;
1067
    //    cur_pc = s->pc; /* for insn generation */
1068
 next_byte:
1069
    b = ldub(s->pc);
1070
    s->pc++;
1071
    /* check prefixes */
1072
    switch (b) {
1073
    case 0xf3:
1074
        prefixes |= PREFIX_REPZ;
1075
        goto next_byte;
1076
    case 0xf2:
1077
        prefixes |= PREFIX_REPNZ;
1078
        goto next_byte;
1079
    case 0xf0:
1080
        prefixes |= PREFIX_LOCK;
1081
        goto next_byte;
1082
    case 0x2e:
1083
        prefixes |= PREFIX_CS;
1084
        goto next_byte;
1085
    case 0x36:
1086
        prefixes |= PREFIX_SS;
1087
        goto next_byte;
1088
    case 0x3e:
1089
        prefixes |= PREFIX_DS;
1090
        goto next_byte;
1091
    case 0x26:
1092
        prefixes |= PREFIX_ES;
1093
        goto next_byte;
1094
    case 0x64:
1095
        prefixes |= PREFIX_FS;
1096
        goto next_byte;
1097
    case 0x65:
1098
        prefixes |= PREFIX_GS;
1099
        goto next_byte;
1100
    case 0x66:
1101
        prefixes |= PREFIX_DATA;
1102
        goto next_byte;
1103
    case 0x67:
1104
        prefixes |= PREFIX_ADR;
1105
        goto next_byte;
1106
    case 0x9b:
1107
        prefixes |= PREFIX_FWAIT;
1108
        goto next_byte;
1109
    }
1110

    
1111
    if (prefixes & PREFIX_DATA)
1112
        dflag ^= 1;
1113
    if (prefixes & PREFIX_ADR)
1114
        aflag ^= 1;
1115

    
1116
    s->prefix = prefixes;
1117
    s->aflag = aflag;
1118
    s->dflag = dflag;
1119

    
1120
    /* now check op code */
1121
 reswitch:
1122
    switch(b) {
1123
    case 0x0f:
1124
        /**************************/
1125
        /* extended op code */
1126
        b = ldub(s->pc++) | 0x100;
1127
        goto reswitch;
1128
        
1129
        /**************************/
1130
        /* arith & logic */
1131
    case 0x00 ... 0x05:
1132
    case 0x08 ... 0x0d:
1133
    case 0x10 ... 0x15:
1134
    case 0x18 ... 0x1d:
1135
    case 0x20 ... 0x25:
1136
    case 0x28 ... 0x2d:
1137
    case 0x30 ... 0x35:
1138
    case 0x38 ... 0x3d:
1139
        {
1140
            int op, f, val;
1141
            op = (b >> 3) & 7;
1142
            f = (b >> 1) & 3;
1143

    
1144
            if ((b & 1) == 0)
1145
                ot = OT_BYTE;
1146
            else
1147
                ot = dflag ? OT_LONG : OT_WORD;
1148
            
1149
            switch(f) {
1150
            case 0: /* OP Ev, Gv */
1151
                modrm = ldub(s->pc++);
1152
                reg = ((modrm >> 3) & 7) + OR_EAX;
1153
                mod = (modrm >> 6) & 3;
1154
                rm = modrm & 7;
1155
                if (mod != 3) {
1156
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1157
                    gen_op_ld_T0_A0[ot]();
1158
                    opreg = OR_TMP0;
1159
                } else {
1160
                    opreg = OR_EAX + rm;
1161
                }
1162
                gen_op(s, op, ot, opreg, reg);
1163
                if (mod != 3 && op != 7) {
1164
                    gen_op_st_T0_A0[ot]();
1165
                }
1166
                break;
1167
            case 1: /* OP Gv, Ev */
1168
                modrm = ldub(s->pc++);
1169
                mod = (modrm >> 6) & 3;
1170
                reg = ((modrm >> 3) & 7) + OR_EAX;
1171
                rm = modrm & 7;
1172
                if (mod != 3) {
1173
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1174
                    gen_op_ld_T1_A0[ot]();
1175
                    opreg = OR_TMP1;
1176
                } else {
1177
                    opreg = OR_EAX + rm;
1178
                }
1179
                gen_op(s, op, ot, reg, opreg);
1180
                break;
1181
            case 2: /* OP A, Iv */
1182
                val = insn_get(s, ot);
1183
                gen_opi(s, op, ot, OR_EAX, val);
1184
                break;
1185
            }
1186
        }
1187
        break;
1188

    
1189
    case 0x80: /* GRP1 */
1190
    case 0x81:
1191
    case 0x83:
1192
        {
1193
            int val;
1194

    
1195
            if ((b & 1) == 0)
1196
                ot = OT_BYTE;
1197
            else
1198
                ot = dflag ? OT_LONG : OT_WORD;
1199
            
1200
            modrm = ldub(s->pc++);
1201
            mod = (modrm >> 6) & 3;
1202
            rm = modrm & 7;
1203
            op = (modrm >> 3) & 7;
1204
            
1205
            if (mod != 3) {
1206
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1207
                gen_op_ld_T0_A0[ot]();
1208
                opreg = OR_TMP0;
1209
            } else {
1210
                opreg = rm + OR_EAX;
1211
            }
1212

    
1213
            switch(b) {
1214
            default:
1215
            case 0x80:
1216
            case 0x81:
1217
                val = insn_get(s, ot);
1218
                break;
1219
            case 0x83:
1220
                val = (int8_t)insn_get(s, OT_BYTE);
1221
                break;
1222
            }
1223

    
1224
            gen_opi(s, op, ot, opreg, val);
1225
            if (op != 7 && mod != 3) {
1226
                gen_op_st_T0_A0[ot]();
1227
            }
1228
        }
1229
        break;
1230

    
1231
        /**************************/
1232
        /* inc, dec, and other misc arith */
1233
    case 0x40 ... 0x47: /* inc Gv */
1234
        ot = dflag ? OT_LONG : OT_WORD;
1235
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1236
        break;
1237
    case 0x48 ... 0x4f: /* dec Gv */
1238
        ot = dflag ? OT_LONG : OT_WORD;
1239
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1240
        break;
1241
    case 0xf6: /* GRP3 */
1242
    case 0xf7:
1243
        if ((b & 1) == 0)
1244
            ot = OT_BYTE;
1245
        else
1246
            ot = dflag ? OT_LONG : OT_WORD;
1247

    
1248
        modrm = ldub(s->pc++);
1249
        mod = (modrm >> 6) & 3;
1250
        rm = modrm & 7;
1251
        op = (modrm >> 3) & 7;
1252
        if (mod != 3) {
1253
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1254
            gen_op_ld_T0_A0[ot]();
1255
        } else {
1256
            gen_op_mov_TN_reg[ot][0][rm]();
1257
        }
1258

    
1259
        switch(op) {
1260
        case 0: /* test */
1261
            val = insn_get(s, ot);
1262
            gen_op_movl_T1_im(val);
1263
            gen_op_testl_T0_T1_cc();
1264
            s->cc_op = CC_OP_LOGICB + ot;
1265
            break;
1266
        case 2: /* not */
1267
            gen_op_notl_T0();
1268
            if (mod != 3) {
1269
                gen_op_st_T0_A0[ot]();
1270
            } else {
1271
                gen_op_mov_reg_T0[ot][rm]();
1272
            }
1273
            break;
1274
        case 3: /* neg */
1275
            gen_op_negl_T0_cc();
1276
            if (mod != 3) {
1277
                gen_op_st_T0_A0[ot]();
1278
            } else {
1279
                gen_op_mov_reg_T0[ot][rm]();
1280
            }
1281
            s->cc_op = CC_OP_SUBB + ot;
1282
            break;
1283
        case 4: /* mul */
1284
            switch(ot) {
1285
            case OT_BYTE:
1286
                gen_op_mulb_AL_T0();
1287
                break;
1288
            case OT_WORD:
1289
                gen_op_mulw_AX_T0();
1290
                break;
1291
            default:
1292
            case OT_LONG:
1293
                gen_op_mull_EAX_T0();
1294
                break;
1295
            }
1296
            s->cc_op = CC_OP_MUL;
1297
            break;
1298
        case 5: /* imul */
1299
            switch(ot) {
1300
            case OT_BYTE:
1301
                gen_op_imulb_AL_T0();
1302
                break;
1303
            case OT_WORD:
1304
                gen_op_imulw_AX_T0();
1305
                break;
1306
            default:
1307
            case OT_LONG:
1308
                gen_op_imull_EAX_T0();
1309
                break;
1310
            }
1311
            s->cc_op = CC_OP_MUL;
1312
            break;
1313
        case 6: /* div */
1314
            switch(ot) {
1315
            case OT_BYTE:
1316
                gen_op_divb_AL_T0();
1317
                break;
1318
            case OT_WORD:
1319
                gen_op_divw_AX_T0();
1320
                break;
1321
            default:
1322
            case OT_LONG:
1323
                gen_op_divl_EAX_T0();
1324
                break;
1325
            }
1326
            break;
1327
        case 7: /* idiv */
1328
            switch(ot) {
1329
            case OT_BYTE:
1330
                gen_op_idivb_AL_T0();
1331
                break;
1332
            case OT_WORD:
1333
                gen_op_idivw_AX_T0();
1334
                break;
1335
            default:
1336
            case OT_LONG:
1337
                gen_op_idivl_EAX_T0();
1338
                break;
1339
            }
1340
            break;
1341
        default:
1342
            error("GRP3: bad instruction");
1343
            return -1;
1344
        }
1345
        break;
1346

    
1347
    case 0xfe: /* GRP4 */
1348
    case 0xff: /* GRP5 */
1349
        if ((b & 1) == 0)
1350
            ot = OT_BYTE;
1351
        else
1352
            ot = dflag ? OT_LONG : OT_WORD;
1353

    
1354
        modrm = ldub(s->pc++);
1355
        mod = (modrm >> 6) & 3;
1356
        rm = modrm & 7;
1357
        op = (modrm >> 3) & 7;
1358
        if (op >= 2 && b == 0xfe) {
1359
            error("GRP4: bad instruction");
1360
            return -1;
1361
        }
1362
        if (mod != 3) {
1363
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1364
            gen_op_ld_T0_A0[ot]();
1365
        } else {
1366
            gen_op_mov_TN_reg[ot][0][rm]();
1367
        }
1368

    
1369
        switch(op) {
1370
        case 0: /* inc Ev */
1371
            gen_inc(s, ot, OR_TMP0, 1);
1372
            if (mod != 3)
1373
                gen_op_st_T0_A0[ot]();
1374
            else
1375
                gen_op_mov_reg_T0[ot][rm]();
1376
            break;
1377
        case 1: /* dec Ev */
1378
            gen_inc(s, ot, OR_TMP0, -1);
1379
            if (mod != 3)
1380
                gen_op_st_T0_A0[ot]();
1381
            else
1382
                gen_op_mov_reg_T0[ot][rm]();
1383
            break;
1384
        case 2: /* call Ev */
1385
            gen_op_movl_T1_im((long)s->pc);
1386
            gen_op_pushl_T1();
1387
            gen_op_jmp_T0();
1388
            *is_jmp_ptr = 1;
1389
            break;
1390
        case 4: /* jmp Ev */
1391
            gen_op_jmp_T0();
1392
            *is_jmp_ptr = 1;
1393
            break;
1394
        case 6: /* push Ev */
1395
            gen_op_pushl_T0();
1396
            break;
1397
        default:
1398
            error("GRP5: bad instruction");
1399
            return -1;
1400
        }
1401
        break;
1402

    
1403
    case 0x84: /* test Ev, Gv */
1404
    case 0x85: 
1405
        if ((b & 1) == 0)
1406
            ot = OT_BYTE;
1407
        else
1408
            ot = dflag ? OT_LONG : OT_WORD;
1409

    
1410
        modrm = ldub(s->pc++);
1411
        mod = (modrm >> 6) & 3;
1412
        rm = modrm & 7;
1413
        reg = (modrm >> 3) & 7;
1414
        
1415
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1416
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1417
        gen_op_testl_T0_T1_cc();
1418
        s->cc_op = CC_OP_LOGICB + ot;
1419
        break;
1420
        
1421
    case 0xa8: /* test eAX, Iv */
1422
    case 0xa9:
1423
        if ((b & 1) == 0)
1424
            ot = OT_BYTE;
1425
        else
1426
            ot = dflag ? OT_LONG : OT_WORD;
1427
        val = insn_get(s, ot);
1428

    
1429
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1430
        gen_op_movl_T1_im(val);
1431
        gen_op_testl_T0_T1_cc();
1432
        s->cc_op = CC_OP_LOGICB + ot;
1433
        break;
1434
        
1435
    case 0x98: /* CWDE/CBW */
1436
        if (dflag)
1437
            gen_op_movswl_EAX_AX();
1438
        else
1439
            gen_op_movsbw_AX_AL();
1440
        break;
1441
    case 0x99: /* CDQ/CWD */
1442
        if (dflag)
1443
            gen_op_movslq_EDX_EAX();
1444
        else
1445
            gen_op_movswl_DX_AX();
1446
        break;
1447
    case 0x1af: /* imul Gv, Ev */
1448
    case 0x69: /* imul Gv, Ev, I */
1449
    case 0x6b:
1450
        ot = dflag ? OT_LONG : OT_WORD;
1451
        modrm = ldub(s->pc++);
1452
        reg = ((modrm >> 3) & 7) + OR_EAX;
1453
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1454
        if (b == 0x69) {
1455
            val = insn_get(s, ot);
1456
            gen_op_movl_T1_im(val);
1457
        } else if (b == 0x6b) {
1458
            val = insn_get(s, OT_BYTE);
1459
            gen_op_movl_T1_im(val);
1460
        } else {
1461
            gen_op_mov_TN_reg[ot][1][reg]();
1462
        }
1463

    
1464
        if (ot == OT_LONG) {
1465
            gen_op_imull_T0_T1();
1466
        } else {
1467
            gen_op_imulw_T0_T1();
1468
        }
1469
        gen_op_mov_reg_T0[ot][reg]();
1470
        s->cc_op = CC_OP_MUL;
1471
        break;
1472
        
1473
        /**************************/
1474
        /* push/pop */
1475
    case 0x50 ... 0x57: /* push */
1476
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1477
        gen_op_pushl_T0();
1478
        break;
1479
    case 0x58 ... 0x5f: /* pop */
1480
        gen_op_popl_T0();
1481
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1482
        break;
1483
    case 0x68: /* push Iv */
1484
    case 0x6a:
1485
        ot = dflag ? OT_LONG : OT_WORD;
1486
        if (b == 0x68)
1487
            val = insn_get(s, ot);
1488
        else
1489
            val = (int8_t)insn_get(s, OT_BYTE);
1490
        gen_op_movl_T0_im(val);
1491
        gen_op_pushl_T0();
1492
        break;
1493
    case 0x8f: /* pop Ev */
1494
        ot = dflag ? OT_LONG : OT_WORD;
1495
        modrm = ldub(s->pc++);
1496
        gen_op_popl_T0();
1497
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1498
        break;
1499
    case 0xc9: /* leave */
1500
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1501
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1502
        gen_op_popl_T0();
1503
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1504
        break;
1505
        /**************************/
1506
        /* mov */
1507
    case 0x88:
1508
    case 0x89: /* mov Gv, Ev */
1509
        if ((b & 1) == 0)
1510
            ot = OT_BYTE;
1511
        else
1512
            ot = dflag ? OT_LONG : OT_WORD;
1513
        modrm = ldub(s->pc++);
1514
        reg = (modrm >> 3) & 7;
1515
        
1516
        /* generate a generic store */
1517
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1518
        break;
1519
    case 0xc6:
1520
    case 0xc7: /* mov Ev, Iv */
1521
        if ((b & 1) == 0)
1522
            ot = OT_BYTE;
1523
        else
1524
            ot = dflag ? OT_LONG : OT_WORD;
1525
        modrm = ldub(s->pc++);
1526
        mod = (modrm >> 6) & 3;
1527
        if (mod != 3)
1528
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1529
        val = insn_get(s, ot);
1530
        gen_op_movl_T0_im(val);
1531
        if (mod != 3)
1532
            gen_op_st_T0_A0[ot]();
1533
        else
1534
            gen_op_mov_reg_T0[ot][modrm & 7]();
1535
        break;
1536
    case 0x8a:
1537
    case 0x8b: /* mov Ev, Gv */
1538
        if ((b & 1) == 0)
1539
            ot = OT_BYTE;
1540
        else
1541
            ot = dflag ? OT_LONG : OT_WORD;
1542
        modrm = ldub(s->pc++);
1543
        reg = (modrm >> 3) & 7;
1544
        
1545
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1546
        gen_op_mov_reg_T0[ot][reg]();
1547
        break;
1548

    
1549
    case 0x1b6: /* movzbS Gv, Eb */
1550
    case 0x1b7: /* movzwS Gv, Eb */
1551
    case 0x1be: /* movsbS Gv, Eb */
1552
    case 0x1bf: /* movswS Gv, Eb */
1553
        {
1554
            int d_ot;
1555
            /* d_ot is the size of destination */
1556
            d_ot = dflag + OT_WORD;
1557
            /* ot is the size of source */
1558
            ot = (b & 1) + OT_BYTE;
1559
            modrm = ldub(s->pc++);
1560
            reg = ((modrm >> 3) & 7) + OR_EAX;
1561
            mod = (modrm >> 6) & 3;
1562
            rm = modrm & 7;
1563
            
1564
            if (mod == 3) {
1565
                gen_op_mov_TN_reg[ot][0][rm]();
1566
                switch(ot | (b & 8)) {
1567
                case OT_BYTE:
1568
                    gen_op_movzbl_T0_T0();
1569
                    break;
1570
                case OT_BYTE | 8:
1571
                    gen_op_movsbl_T0_T0();
1572
                    break;
1573
                case OT_WORD:
1574
                    gen_op_movzwl_T0_T0();
1575
                    break;
1576
                default:
1577
                case OT_WORD | 8:
1578
                    gen_op_movswl_T0_T0();
1579
                    break;
1580
                }
1581
                gen_op_mov_reg_T0[d_ot][reg]();
1582
            } else {
1583
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1584
                if (b & 8) {
1585
                    gen_op_lds_T0_A0[ot]();
1586
                } else {
1587
                    gen_op_ldu_T0_A0[ot]();
1588
                }
1589
                gen_op_mov_reg_T0[d_ot][reg]();
1590
            }
1591
        }
1592
        break;
1593

    
1594
    case 0x8d: /* lea */
1595
        ot = dflag ? OT_LONG : OT_WORD;
1596
        modrm = ldub(s->pc++);
1597
        reg = (modrm >> 3) & 7;
1598

    
1599
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1600
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1601
        break;
1602
        
1603
    case 0xa0: /* mov EAX, Ov */
1604
    case 0xa1:
1605
    case 0xa2: /* mov Ov, EAX */
1606
    case 0xa3:
1607
        if ((b & 1) == 0)
1608
            ot = OT_BYTE;
1609
        else
1610
            ot = dflag ? OT_LONG : OT_WORD;
1611
        if (s->aflag)
1612
            offset_addr = insn_get(s, OT_LONG);
1613
        else
1614
            offset_addr = insn_get(s, OT_WORD);
1615
        gen_op_movl_A0_im(offset_addr);
1616
        if ((b & 2) == 0) {
1617
            gen_op_ld_T0_A0[ot]();
1618
            gen_op_mov_reg_T0[ot][R_EAX]();
1619
        } else {
1620
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1621
            gen_op_st_T0_A0[ot]();
1622
        }
1623
        break;
1624

    
1625
    case 0xb0 ... 0xb7: /* mov R, Ib */
1626
        val = insn_get(s, OT_BYTE);
1627
        gen_op_movl_T0_im(val);
1628
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1629
        break;
1630
    case 0xb8 ... 0xbf: /* mov R, Iv */
1631
        ot = dflag ? OT_LONG : OT_WORD;
1632
        val = insn_get(s, ot);
1633
        reg = OR_EAX + (b & 7);
1634
        gen_op_movl_T0_im(val);
1635
        gen_op_mov_reg_T0[ot][reg]();
1636
        break;
1637

    
1638
    case 0x91 ... 0x97: /* xchg R, EAX */
1639
        ot = dflag ? OT_LONG : OT_WORD;
1640
        reg = b & 7;
1641
        gen_op_mov_TN_reg[ot][0][reg]();
1642
        gen_op_mov_TN_reg[ot][1][R_EAX]();
1643
        gen_op_mov_reg_T0[ot][R_EAX]();
1644
        gen_op_mov_reg_T1[ot][reg]();
1645
        break;
1646
    case 0x86:
1647
    case 0x87: /* xchg Ev, Gv */
1648
        if ((b & 1) == 0)
1649
            ot = OT_BYTE;
1650
        else
1651
            ot = dflag ? OT_LONG : OT_WORD;
1652
        modrm = ldub(s->pc++);
1653
        reg = (modrm >> 3) & 7;
1654

    
1655
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1656
        gen_op_mov_TN_reg[ot][0][reg]();
1657
        gen_op_ld_T1_A0[ot]();
1658
        gen_op_st_T0_A0[ot]();
1659
        gen_op_mov_reg_T1[ot][reg]();
1660
        break;
1661
        
1662
        /************************/
1663
        /* shifts */
1664
    case 0xc0:
1665
    case 0xc1:
1666
        /* shift Ev,Ib */
1667
        shift = 2;
1668
    grp2:
1669
        {
1670
            if ((b & 1) == 0)
1671
                ot = OT_BYTE;
1672
            else
1673
                ot = dflag ? OT_LONG : OT_WORD;
1674
            
1675
            modrm = ldub(s->pc++);
1676
            mod = (modrm >> 6) & 3;
1677
            rm = modrm & 7;
1678
            op = (modrm >> 3) & 7;
1679
            
1680
            if (mod != 3) {
1681
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1682
                gen_op_ld_T0_A0[ot]();
1683
                opreg = OR_TMP0;
1684
            } else {
1685
                opreg = rm + OR_EAX;
1686
            }
1687

    
1688
            /* simpler op */
1689
            if (shift == 0) {
1690
                gen_shift(s, op, ot, opreg, OR_ECX);
1691
            } else {
1692
                if (shift == 2) {
1693
                    shift = ldub(s->pc++);
1694
                }
1695
                gen_shifti(s, op, ot, opreg, shift);
1696
            }
1697

    
1698
            if (mod != 3) {
1699
                gen_op_st_T0_A0[ot]();
1700
            }
1701
        }
1702
        break;
1703
    case 0xd0:
1704
    case 0xd1:
1705
        /* shift Ev,1 */
1706
        shift = 1;
1707
        goto grp2;
1708
    case 0xd2:
1709
    case 0xd3:
1710
        /* shift Ev,cl */
1711
        shift = 0;
1712
        goto grp2;
1713

    
1714
    case 0x1a4: /* shld imm */
1715
        op = 0;
1716
        shift = 1;
1717
        goto do_shiftd;
1718
    case 0x1a5: /* shld cl */
1719
        op = 0;
1720
        shift = 0;
1721
        goto do_shiftd;
1722
    case 0x1ac: /* shrd imm */
1723
        op = 1;
1724
        shift = 1;
1725
        goto do_shiftd;
1726
    case 0x1ad: /* shrd cl */
1727
        op = 1;
1728
        shift = 0;
1729
    do_shiftd:
1730
        ot = dflag ? OT_LONG : OT_WORD;
1731
        modrm = ldub(s->pc++);
1732
        mod = (modrm >> 6) & 3;
1733
        rm = modrm & 7;
1734
        reg = (modrm >> 3) & 7;
1735
        
1736
        if (mod != 3) {
1737
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1738
            gen_op_ld_T0_A0[ot]();
1739
        } else {
1740
            gen_op_mov_TN_reg[ot][0][rm]();
1741
        }
1742
        gen_op_mov_TN_reg[ot][1][reg]();
1743
        
1744
        if (shift) {
1745
            val = ldub(s->pc++);
1746
            val &= 0x1f;
1747
            if (val) {
1748
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1749
                if (op == 0 && ot != OT_WORD)
1750
                    s->cc_op = CC_OP_SHLB + ot;
1751
                else
1752
                    s->cc_op = CC_OP_SARB + ot;
1753
            }
1754
        } else {
1755
            if (s->cc_op != CC_OP_DYNAMIC)
1756
                gen_op_set_cc_op(s->cc_op);
1757
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1758
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1759
        }
1760
        if (mod != 3) {
1761
            gen_op_st_T0_A0[ot]();
1762
        } else {
1763
            gen_op_mov_reg_T0[ot][rm]();
1764
        }
1765
        break;
1766

    
1767
        /************************/
1768
        /* floats */
1769
    case 0xd8 ... 0xdf: 
1770
        modrm = ldub(s->pc++);
1771
        mod = (modrm >> 6) & 3;
1772
        rm = modrm & 7;
1773
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1774
        
1775
        if (mod != 3) {
1776
            /* memory op */
1777
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1778
            switch(op) {
1779
            case 0x00 ... 0x07: /* fxxxs */
1780
            case 0x10 ... 0x17: /* fixxxl */
1781
            case 0x20 ... 0x27: /* fxxxl */
1782
            case 0x30 ... 0x37: /* fixxx */
1783
                {
1784
                    int op1;
1785
                    op1 = op & 7;
1786

    
1787
                    switch(op >> 4) {
1788
                    case 0:
1789
                        gen_op_flds_FT0_A0();
1790
                        break;
1791
                    case 1:
1792
                        gen_op_fildl_FT0_A0();
1793
                        break;
1794
                    case 2:
1795
                        gen_op_fldl_FT0_A0();
1796
                        break;
1797
                    case 3:
1798
                    default:
1799
                        gen_op_fild_FT0_A0();
1800
                        break;
1801
                    }
1802
                    
1803
                    gen_op_fp_arith_ST0_FT0[op1]();
1804
                    if (op1 == 3) {
1805
                        /* fcomp needs pop */
1806
                        gen_op_fpop();
1807
                    }
1808
                }
1809
                break;
1810
            case 0x08: /* flds */
1811
            case 0x0a: /* fsts */
1812
            case 0x0b: /* fstps */
1813
            case 0x18: /* fildl */
1814
            case 0x1a: /* fistl */
1815
            case 0x1b: /* fistpl */
1816
            case 0x28: /* fldl */
1817
            case 0x2a: /* fstl */
1818
            case 0x2b: /* fstpl */
1819
            case 0x38: /* filds */
1820
            case 0x3a: /* fists */
1821
            case 0x3b: /* fistps */
1822
                
1823
                switch(op & 7) {
1824
                case 0:
1825
                    gen_op_fpush();
1826
                    switch(op >> 4) {
1827
                    case 0:
1828
                        gen_op_flds_ST0_A0();
1829
                        break;
1830
                    case 1:
1831
                        gen_op_fildl_ST0_A0();
1832
                        break;
1833
                    case 2:
1834
                        gen_op_fldl_ST0_A0();
1835
                        break;
1836
                    case 3:
1837
                    default:
1838
                        gen_op_fild_ST0_A0();
1839
                        break;
1840
                    }
1841
                    break;
1842
                default:
1843
                    switch(op >> 4) {
1844
                    case 0:
1845
                        gen_op_fsts_ST0_A0();
1846
                        break;
1847
                    case 1:
1848
                        gen_op_fistl_ST0_A0();
1849
                        break;
1850
                    case 2:
1851
                        gen_op_fstl_ST0_A0();
1852
                        break;
1853
                    case 3:
1854
                    default:
1855
                        gen_op_fist_ST0_A0();
1856
                        break;
1857
                    }
1858
                    if ((op & 7) == 3)
1859
                        gen_op_fpop();
1860
                    break;
1861
                }
1862
                break;
1863
            case 0x0d: /* fldcw mem */
1864
                gen_op_fldcw_A0();
1865
                break;
1866
            case 0x0f: /* fnstcw mem */
1867
                gen_op_fnstcw_A0();
1868
                break;
1869
            case 0x2f: /* fnstsw mem */
1870
                gen_op_fnstsw_A0();
1871
                break;
1872
            case 0x3c: /* fbld */
1873
            case 0x3e: /* fbstp */
1874
                error("float BCD not hanlded");
1875
                return -1;
1876
            case 0x3d: /* fildll */
1877
                gen_op_fpush();
1878
                gen_op_fildll_ST0_A0();
1879
                break;
1880
            case 0x3f: /* fistpll */
1881
                gen_op_fistll_ST0_A0();
1882
                gen_op_fpop();
1883
                break;
1884
            default:
1885
                error("unhandled memory FP [op=0x%02x]\n", op);
1886
                return -1;
1887
            }
1888
        } else {
1889
            /* register float ops */
1890
            opreg = rm;
1891

    
1892
            switch(op) {
1893
            case 0x08: /* fld sti */
1894
                gen_op_fpush();
1895
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
1896
                break;
1897
            case 0x09: /* fxchg sti */
1898
                gen_op_fxchg_ST0_STN((opreg + 1) & 7);
1899
                break;
1900
            case 0x0a: /* grp d9/2 */
1901
                switch(rm) {
1902
                case 0: /* fnop */
1903
                    break;
1904
                default:
1905
                    error("unhandled FP GRP d9/2\n");
1906
                    return -1;
1907
                }
1908
                break;
1909
            case 0x0c: /* grp d9/4 */
1910
                switch(rm) {
1911
                case 0: /* fchs */
1912
                    gen_op_fchs_ST0();
1913
                    break;
1914
                case 1: /* fabs */
1915
                    gen_op_fabs_ST0();
1916
                    break;
1917
                case 4: /* ftst */
1918
                    gen_op_fldz_FT0();
1919
                    gen_op_fcom_ST0_FT0();
1920
                    break;
1921
                case 5: /* fxam */
1922
                    gen_op_fxam_ST0();
1923
                    break;
1924
                default:
1925
                    return -1;
1926
                }
1927
                break;
1928
            case 0x0d: /* grp d9/5 */
1929
                {
1930
                    switch(rm) {
1931
                    case 0:
1932
                        gen_op_fld1_ST0();
1933
                        break;
1934
                    case 1:
1935
                        gen_op_fld2t_ST0();
1936
                        break;
1937
                    case 2:
1938
                        gen_op_fld2e_ST0();
1939
                        break;
1940
                    case 3:
1941
                        gen_op_fldpi_ST0();
1942
                        break;
1943
                    case 4:
1944
                        gen_op_fldlg2_ST0();
1945
                        break;
1946
                    case 5:
1947
                        gen_op_fldln2_ST0();
1948
                        break;
1949
                    case 6:
1950
                        gen_op_fldz_ST0();
1951
                        break;
1952
                    default:
1953
                        return -1;
1954
                    }
1955
                }
1956
                break;
1957
            case 0x0e: /* grp d9/6 */
1958
                switch(rm) {
1959
                case 0: /* f2xm1 */
1960
                    gen_op_f2xm1();
1961
                    break;
1962
                case 1: /* fyl2x */
1963
                    gen_op_fyl2x();
1964
                    break;
1965
                case 2: /* fptan */
1966
                    gen_op_fptan();
1967
                    break;
1968
                case 3: /* fpatan */
1969
                    gen_op_fpatan();
1970
                    break;
1971
                case 4: /* fxtract */
1972
                    gen_op_fxtract();
1973
                    break;
1974
                case 5: /* fprem1 */
1975
                    gen_op_fprem1();
1976
                    break;
1977
                case 6: /* fdecstp */
1978
                    gen_op_fdecstp();
1979
                    break;
1980
                default:
1981
                case 7: /* fincstp */
1982
                    gen_op_fincstp();
1983
                    break;
1984
                }
1985
                break;
1986
            case 0x0f: /* grp d9/7 */
1987
                switch(rm) {
1988
                case 0: /* fprem */
1989
                    gen_op_fprem();
1990
                    break;
1991
                case 1: /* fyl2xp1 */
1992
                    gen_op_fyl2xp1();
1993
                    break;
1994
                case 2: /* fsqrt */
1995
                    gen_op_fsqrt();
1996
                    break;
1997
                case 3: /* fsincos */
1998
                    gen_op_fsincos();
1999
                    break;
2000
                case 5: /* fscale */
2001
                    gen_op_fscale();
2002
                    break;
2003
                case 4: /* frndint */
2004
                    gen_op_frndint();
2005
                    break;
2006
                case 6: /* fsin */
2007
                    gen_op_fsin();
2008
                    break;
2009
                default:
2010
                case 7: /* fcos */
2011
                    gen_op_fcos();
2012
                    break;
2013
                }
2014
                break;
2015
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2016
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2017
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2018
                {
2019
                    int op1;
2020
                    
2021
                    op1 = op & 7;
2022
                    if (op >= 0x20) {
2023
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2024
                    } else {
2025
                        gen_op_fmov_FT0_STN(opreg);
2026
                        gen_op_fp_arith_ST0_FT0[op1]();
2027
                    }
2028
                    if (op >= 0x30)
2029
                        gen_op_fpop();
2030
                }
2031
                break;
2032
            case 0x02: /* fcom */
2033
                gen_op_fmov_FT0_STN(opreg);
2034
                gen_op_fcom_ST0_FT0();
2035
                break;
2036
            case 0x03: /* fcomp */
2037
                gen_op_fmov_FT0_STN(opreg);
2038
                gen_op_fcom_ST0_FT0();
2039
                gen_op_fpop();
2040
                break;
2041
            case 0x15: /* da/5 */
2042
                switch(rm) {
2043
                case 1: /* fucompp */
2044
                    gen_op_fmov_FT0_STN(1);
2045
                    gen_op_fcom_ST0_FT0();
2046
                    gen_op_fpop();
2047
                    gen_op_fpop();
2048
                    break;
2049
                default:
2050
                    return -1;
2051
                }
2052
                break;
2053
            case 0x2a: /* fst sti */
2054
                gen_op_fmov_STN_ST0(opreg);
2055
                break;
2056
            case 0x2b: /* fstp sti */
2057
                gen_op_fmov_STN_ST0(opreg);
2058
                gen_op_fpop();
2059
                break;
2060
            case 0x33: /* de/3 */
2061
                switch(rm) {
2062
                case 1: /* fcompp */
2063
                    gen_op_fmov_FT0_STN(1);
2064
                    gen_op_fcom_ST0_FT0();
2065
                    gen_op_fpop();
2066
                    gen_op_fpop();
2067
                    break;
2068
                default:
2069
                    return -1;
2070
                }
2071
                break;
2072
            case 0x3c: /* df/4 */
2073
                switch(rm) {
2074
#if 0
2075
                case 0:
2076
                    gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
2077
                    break;
2078
#endif
2079
                default:
2080
                    error("unhandled FP df/4\n");
2081
                    return -1;
2082
                }
2083
                break;
2084
            default:
2085
                error("unhandled FP\n");
2086
                return -1;
2087
            }
2088
        }
2089
        break;
2090
        /************************/
2091
        /* string ops */
2092
    case 0xa4: /* movsS */
2093
    case 0xa5:
2094
        if ((b & 1) == 0)
2095
            ot = OT_BYTE;
2096
        else
2097
            ot = dflag ? OT_LONG : OT_WORD;
2098
        if (prefixes & PREFIX_REPZ) {
2099
            gen_op_movs[3 + ot]();
2100
        } else {
2101
            gen_op_movs[ot]();
2102
        }
2103
        break;
2104
        
2105
    case 0xaa: /* stosS */
2106
    case 0xab:
2107
        if ((b & 1) == 0)
2108
            ot = OT_BYTE;
2109
        else
2110
            ot = dflag ? OT_LONG : OT_WORD;
2111
        if (prefixes & PREFIX_REPZ) {
2112
            gen_op_stos[3 + ot]();
2113
        } else {
2114
            gen_op_stos[ot]();
2115
        }
2116
        break;
2117
    case 0xac: /* lodsS */
2118
    case 0xad:
2119
        if ((b & 1) == 0)
2120
            ot = OT_BYTE;
2121
        else
2122
            ot = dflag ? OT_LONG : OT_WORD;
2123
        if (prefixes & PREFIX_REPZ) {
2124
            gen_op_lods[3 + ot]();
2125
        } else {
2126
            gen_op_lods[ot]();
2127
        }
2128
        break;
2129
    case 0xae: /* scasS */
2130
    case 0xaf:
2131
        if ((b & 1) == 0)
2132
            ot = OT_BYTE;
2133
        else
2134
            ot = dflag ? OT_LONG : OT_WORD;
2135
        if (prefixes & PREFIX_REPNZ) {
2136
            if (s->cc_op != CC_OP_DYNAMIC)
2137
                gen_op_set_cc_op(s->cc_op);
2138
            gen_op_scas[6 + ot]();
2139
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2140
        } else if (prefixes & PREFIX_REPZ) {
2141
            if (s->cc_op != CC_OP_DYNAMIC)
2142
                gen_op_set_cc_op(s->cc_op);
2143
            gen_op_scas[3 + ot]();
2144
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2145
        } else {
2146
            gen_op_scas[ot]();
2147
            s->cc_op = CC_OP_SUBB + ot;
2148
        }
2149
        break;
2150

    
2151
    case 0xa6: /* cmpsS */
2152
    case 0xa7:
2153
        if ((b & 1) == 0)
2154
            ot = OT_BYTE;
2155
        else
2156
            ot = dflag ? OT_LONG : OT_WORD;
2157
        if (prefixes & PREFIX_REPNZ) {
2158
            if (s->cc_op != CC_OP_DYNAMIC)
2159
                gen_op_set_cc_op(s->cc_op);
2160
            gen_op_cmps[6 + ot]();
2161
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2162
        } else if (prefixes & PREFIX_REPZ) {
2163
            if (s->cc_op != CC_OP_DYNAMIC)
2164
                gen_op_set_cc_op(s->cc_op);
2165
            gen_op_cmps[3 + ot]();
2166
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2167
        } else {
2168
            gen_op_cmps[ot]();
2169
            s->cc_op = CC_OP_SUBB + ot;
2170
        }
2171
        break;
2172
        
2173
        /************************/
2174
        /* port I/O */
2175
    case 0x6c: /* insS */
2176
    case 0x6d:
2177
        if ((b & 1) == 0)
2178
            ot = OT_BYTE;
2179
        else
2180
            ot = dflag ? OT_LONG : OT_WORD;
2181
        if (prefixes & PREFIX_REPZ) {
2182
            gen_op_ins[3 + ot]();
2183
        } else {
2184
            gen_op_ins[ot]();
2185
        }
2186
        break;
2187
    case 0x6e: /* outsS */
2188
    case 0x6f:
2189
        if ((b & 1) == 0)
2190
            ot = OT_BYTE;
2191
        else
2192
            ot = dflag ? OT_LONG : OT_WORD;
2193
        if (prefixes & PREFIX_REPZ) {
2194
            gen_op_outs[3 + ot]();
2195
        } else {
2196
            gen_op_outs[ot]();
2197
        }
2198
        break;
2199
    case 0xe4:
2200
    case 0xe5:
2201
        if ((b & 1) == 0)
2202
            ot = OT_BYTE;
2203
        else
2204
            ot = dflag ? OT_LONG : OT_WORD;
2205
        val = ldub(s->pc++);
2206
        gen_op_movl_T0_im(val);
2207
        gen_op_in[ot]();
2208
        gen_op_mov_reg_T1[ot][R_EAX]();
2209
        break;
2210
    case 0xe6:
2211
    case 0xe7:
2212
        if ((b & 1) == 0)
2213
            ot = OT_BYTE;
2214
        else
2215
            ot = dflag ? OT_LONG : OT_WORD;
2216
        val = ldub(s->pc++);
2217
        gen_op_movl_T0_im(val);
2218
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2219
        gen_op_out[ot]();
2220
        break;
2221
    case 0xec:
2222
    case 0xed:
2223
        if ((b & 1) == 0)
2224
            ot = OT_BYTE;
2225
        else
2226
            ot = dflag ? OT_LONG : OT_WORD;
2227
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2228
        gen_op_in[ot]();
2229
        gen_op_mov_reg_T1[ot][R_EAX]();
2230
        break;
2231
    case 0xee:
2232
    case 0xef:
2233
        if ((b & 1) == 0)
2234
            ot = OT_BYTE;
2235
        else
2236
            ot = dflag ? OT_LONG : OT_WORD;
2237
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2238
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2239
        gen_op_out[ot]();
2240
        break;
2241

    
2242
        /************************/
2243
        /* control */
2244
    case 0xc2: /* ret im */
2245
        /* XXX: handle stack pop ? */
2246
        val = ldsw(s->pc);
2247
        s->pc += 2;
2248
        gen_op_popl_T0();
2249
        gen_op_addl_ESP_im(val);
2250
        gen_op_jmp_T0();
2251
        *is_jmp_ptr = 1;
2252
        break;
2253
    case 0xc3: /* ret */
2254
        gen_op_popl_T0();
2255
        gen_op_jmp_T0();
2256
        *is_jmp_ptr = 1;
2257
        break;
2258
    case 0xe8: /* call */
2259
        val = insn_get(s, OT_LONG);
2260
        val += (long)s->pc;
2261
        gen_op_movl_T1_im((long)s->pc);
2262
        gen_op_pushl_T1();
2263
        gen_op_jmp_im(val);
2264
        *is_jmp_ptr = 1;
2265
        break;
2266
    case 0xe9: /* jmp */
2267
        val = insn_get(s, OT_LONG);
2268
        val += (long)s->pc;
2269
        gen_op_jmp_im(val);
2270
        *is_jmp_ptr = 1;
2271
        break;
2272
    case 0xeb: /* jmp Jb */
2273
        val = (int8_t)insn_get(s, OT_BYTE);
2274
        val += (long)s->pc;
2275
        gen_op_jmp_im(val);
2276
        *is_jmp_ptr = 1;
2277
        break;
2278
    case 0x70 ... 0x7f: /* jcc Jb */
2279
        val = (int8_t)insn_get(s, OT_BYTE);
2280
        val += (long)s->pc;
2281
        goto do_jcc;
2282
    case 0x180 ... 0x18f: /* jcc Jv */
2283
        if (dflag) {
2284
            val = insn_get(s, OT_LONG);
2285
        } else {
2286
            val = (int16_t)insn_get(s, OT_WORD); 
2287
        }
2288
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2289
    do_jcc:
2290
        gen_jcc(s, b, val);
2291
        *is_jmp_ptr = 1;
2292
        break;
2293

    
2294
    case 0x190 ... 0x19f:
2295
        modrm = ldub(s->pc++);
2296
        gen_setcc(s, b);
2297
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2298
        break;
2299

    
2300
        /************************/
2301
        /* flags */
2302
    case 0x9c: /* pushf */
2303
        gen_op_movl_T0_eflags();
2304
        gen_op_pushl_T0();
2305
        break;
2306
    case 0x9d: /* popf */
2307
        gen_op_popl_T0();
2308
        gen_op_movl_eflags_T0();
2309
        s->cc_op = CC_OP_EFLAGS;
2310
        break;
2311
    case 0x9e: /* sahf */
2312
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2313
        if (s->cc_op != CC_OP_DYNAMIC)
2314
            op_set_cc_op(s->cc_op);
2315
        gen_op_movb_eflags_T0();
2316
        s->cc_op = CC_OP_EFLAGS;
2317
        break;
2318
    case 0x9f: /* lahf */
2319
        if (s->cc_op != CC_OP_DYNAMIC)
2320
            op_set_cc_op(s->cc_op);
2321
        gen_op_movl_T0_eflags();
2322
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2323
        break;
2324
    case 0xf5: /* cmc */
2325
        if (s->cc_op != CC_OP_DYNAMIC)
2326
            op_set_cc_op(s->cc_op);
2327
        gen_op_cmc();
2328
        s->cc_op = CC_OP_EFLAGS;
2329
        break;
2330
    case 0xf8: /* clc */
2331
        if (s->cc_op != CC_OP_DYNAMIC)
2332
            op_set_cc_op(s->cc_op);
2333
        gen_op_clc();
2334
        s->cc_op = CC_OP_EFLAGS;
2335
        break;
2336
    case 0xf9: /* stc */
2337
        if (s->cc_op != CC_OP_DYNAMIC)
2338
            op_set_cc_op(s->cc_op);
2339
        gen_op_stc();
2340
        s->cc_op = CC_OP_EFLAGS;
2341
        break;
2342
    case 0xfc: /* cld */
2343
        gen_op_cld();
2344
        break;
2345
    case 0xfd: /* std */
2346
        gen_op_std();
2347
        break;
2348

    
2349
        /************************/
2350
        /* bit operations */
2351
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
2352
        ot = dflag ? OT_LONG : OT_WORD;
2353
        modrm = ldub(s->pc++);
2354
        op = (modrm >> 3) & 7;
2355
        mod = (modrm >> 6) & 3;
2356
        rm = modrm & 7;
2357
        if (mod != 3) {
2358
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2359
            gen_op_ld_T0_A0[ot]();
2360
        } else {
2361
            gen_op_mov_TN_reg[ot][0][rm]();
2362
        }
2363
        /* load shift */
2364
        val = ldub(s->pc++);
2365
        gen_op_movl_T1_im(val);
2366
        if (op < 4)
2367
            return -1;
2368
        op -= 4;
2369
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2370
        s->cc_op = CC_OP_SARB + ot;
2371
        if (op != 0) {
2372
            if (mod != 3)
2373
                gen_op_st_T0_A0[ot]();
2374
            else
2375
                gen_op_mov_reg_T0[ot][rm]();
2376
        }
2377
        break;
2378
    case 0x1a3: /* bt Gv, Ev */
2379
        op = 0;
2380
        goto do_btx;
2381
    case 0x1ab: /* bts */
2382
        op = 1;
2383
        goto do_btx;
2384
    case 0x1b3: /* btr */
2385
        op = 2;
2386
        goto do_btx;
2387
    case 0x1bb: /* btc */
2388
        op = 3;
2389
    do_btx:
2390
        ot = dflag ? OT_LONG : OT_WORD;
2391
        modrm = ldub(s->pc++);
2392
        reg = (modrm >> 3) & 7;
2393
        mod = (modrm >> 6) & 3;
2394
        rm = modrm & 7;
2395
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
2396
        if (mod != 3) {
2397
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2398
            /* specific case: we need to add a displacement */
2399
            if (ot == OT_WORD)
2400
                gen_op_add_bitw_A0_T1();
2401
            else
2402
                gen_op_add_bitl_A0_T1();
2403
            gen_op_ld_T0_A0[ot]();
2404
        } else {
2405
            gen_op_mov_TN_reg[ot][0][rm]();
2406
        }
2407
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2408
        s->cc_op = CC_OP_SARB + ot;
2409
        if (op != 0) {
2410
            if (mod != 3)
2411
                gen_op_st_T0_A0[ot]();
2412
            else
2413
                gen_op_mov_reg_T0[ot][rm]();
2414
        }
2415
        break;
2416

    
2417
        /************************/
2418
        /* misc */
2419
    case 0x90: /* nop */
2420
        break;
2421
    case 0xcc: /* int3 */
2422
        gen_op_int3((long)pc_start);
2423
        *is_jmp_ptr = 1;
2424
        break;
2425
    case 0xcd: /* int N */
2426
        val = ldub(s->pc++);
2427
        /* XXX: currently we ignore the interrupt number */
2428
        gen_op_int_im((long)pc_start);
2429
        *is_jmp_ptr = 1;
2430
        break;
2431
    case 0xce: /* into */
2432
        if (s->cc_op != CC_OP_DYNAMIC)
2433
            gen_op_set_cc_op(s->cc_op);
2434
        gen_op_into((long)pc_start, (long)s->pc);
2435
        *is_jmp_ptr = 1;
2436
        break;
2437
    case 0x1c8 ... 0x1cf: /* bswap reg */
2438
      reg = b & 7;
2439
      gen_op_mov_TN_reg[OT_LONG][0][reg]();
2440
      gen_op_bswapl_T0();
2441
      gen_op_mov_reg_T0[OT_LONG][reg]();
2442
      break;
2443
      
2444
#if 0
2445
    case 0x1a2: /* cpuid */
2446
        gen_insn0(OP_ASM);
2447
        break;
2448
#endif
2449
    default:
2450
        error("unknown opcode %x", b);
2451
        return -1;
2452
    }
2453
    return (long)s->pc;
2454
}
2455

    
2456
/* return the next pc */
2457
int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
2458
                     uint8_t *pc_start)
2459
{
2460
    DisasContext dc1, *dc = &dc1;
2461
    int is_jmp;
2462
    long ret;
2463
#ifdef DEBUG_DISAS
2464
    struct disassemble_info disasm_info;
2465
#endif
2466

    
2467
    dc->cc_op = CC_OP_DYNAMIC;
2468
    gen_code_ptr = gen_code_buf;
2469
    gen_start();
2470

    
2471
#ifdef DEBUG_DISAS
2472
    if (loglevel) {
2473
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2474
        disasm_info.buffer = pc_start;
2475
        disasm_info.buffer_vma = (unsigned long)pc_start;
2476
        disasm_info.buffer_length = 15;
2477
#if 0        
2478
        disasm_info.flavour = bfd_get_flavour (abfd);
2479
        disasm_info.arch = bfd_get_arch (abfd);
2480
        disasm_info.mach = bfd_get_mach (abfd);
2481
#endif
2482
#ifdef WORDS_BIGENDIAN
2483
        disasm_info.endian = BFD_ENDIAN_BIG;
2484
#else
2485
        disasm_info.endian = BFD_ENDIAN_LITTLE;
2486
#endif        
2487
        fprintf(logfile, "IN:\n");
2488
        fprintf(logfile, "0x%08lx:  ", (long)pc_start);
2489
        print_insn_i386((unsigned long)pc_start, &disasm_info);
2490
        fprintf(logfile, "\n\n");
2491
    }
2492
#endif
2493
    is_jmp = 0;
2494
    ret = disas_insn(dc, pc_start, &is_jmp);
2495
    if (ret == -1) 
2496
        error("unknown instruction at PC=0x%x B=%02x %02x", 
2497
              pc_start, pc_start[0], pc_start[1]);
2498
    /* we must store the eflags state if it is not already done */
2499
    if (dc->cc_op != CC_OP_DYNAMIC)
2500
        gen_op_set_cc_op(dc->cc_op);
2501
    if (!is_jmp) {
2502
        /* we add an additionnal jmp to update the simulated PC */
2503
        gen_op_jmp_im(ret);
2504
    }
2505
    gen_end();
2506
    *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2507

    
2508
#ifdef DEBUG_DISAS
2509
    if (loglevel) {
2510
        uint8_t *pc;
2511
        int count;
2512

    
2513
        pc = gen_code_buf;
2514
        disasm_info.buffer = pc;
2515
        disasm_info.buffer_vma = (unsigned long)pc;
2516
        disasm_info.buffer_length = *gen_code_size_ptr;
2517
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2518
        while (pc < gen_code_ptr) {
2519
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2520
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2521
            fprintf(logfile, "\n");
2522
            pc += count;
2523
        }
2524
        fprintf(logfile, "\n");
2525
    }
2526
#endif
2527
    return 0;
2528
}
2529

    
2530
CPUX86State *cpu_x86_init(void)
2531
{
2532
    CPUX86State *env;
2533
    int i;
2534

    
2535
    env = malloc(sizeof(CPUX86State));
2536
    if (!env)
2537
        return NULL;
2538
    memset(env, 0, sizeof(CPUX86State));
2539
    /* basic FPU init */
2540
    for(i = 0;i < 8; i++)
2541
        env->fptags[i] = 1;
2542
    env->fpuc = 0x37f;
2543
    /* flags setup */
2544
    env->cc_op = CC_OP_EFLAGS;
2545
    env->df = 1;
2546
    return env;
2547
}
2548

    
2549
void cpu_x86_close(CPUX86State *env)
2550
{
2551
    free(env);
2552
}