Statistics
| Branch: | Revision:

root / translate-i386.c @ 1a9353d2

History | View | Annotate | Download (76.6 kB)

1
/*
2
 *  i386 translation
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <assert.h>
26

    
27
#define DEBUG_DISAS
28

    
29
#define IN_OP_I386
30
#include "cpu-i386.h"
31

    
32
/* dump all code */
33
#ifdef DEBUG_DISAS
34
#include "dis-asm.h"
35
#endif
36

    
37
#ifndef offsetof
38
#define offsetof(type, field) ((size_t) &((type *)0)->field)
39
#endif
40

    
41
static uint8_t *gen_code_ptr;
42
int __op_param1, __op_param2, __op_param3;
43

    
44
extern FILE *logfile;
45
extern int loglevel;
46

    
47
/* supress that */
48
static void error(const char *fmt, ...)
49
{
50
    va_list ap;
51

    
52
    va_start(ap, fmt);
53
    fprintf(stderr, "\n");
54
    vfprintf(stderr, fmt, ap);
55
    fprintf(stderr, "\n");
56
    va_end(ap);
57
    exit(1);
58
}
59

    
60
#define PREFIX_REPZ 1
61
#define PREFIX_REPNZ 2
62
#define PREFIX_LOCK 4
63
#define PREFIX_CS 8
64
#define PREFIX_SS 0x10
65
#define PREFIX_DS 0x20
66
#define PREFIX_ES 0x40
67
#define PREFIX_FS 0x80
68
#define PREFIX_GS 0x100
69
#define PREFIX_DATA 0x200
70
#define PREFIX_ADR 0x400
71
#define PREFIX_FWAIT 0x800
72

    
73
typedef struct DisasContext {
74
    /* current insn context */
75
    int prefix;
76
    int aflag, dflag;
77
    uint8_t *pc; /* current pc */
78
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
79
                   static state change (stop translation) */
80
    /* current block context */
81
    int code32; /* 32 bit code segment */
82
    int cc_op;  /* current CC operation */
83
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
84
    int f_st;   /* currently unused */
85
} DisasContext;
86

    
87
/* i386 arith/logic operations */
88
enum {
89
    OP_ADDL, 
90
    OP_ORL, 
91
    OP_ADCL, 
92
    OP_SBBL,
93
    OP_ANDL, 
94
    OP_SUBL, 
95
    OP_XORL, 
96
    OP_CMPL,
97
};
98

    
99
/* i386 shift ops */
100
enum {
101
    OP_ROL, 
102
    OP_ROR, 
103
    OP_RCL, 
104
    OP_RCR, 
105
    OP_SHL, 
106
    OP_SHR, 
107
    OP_SHL1, /* undocumented */
108
    OP_SAR = 7,
109
};
110

    
111
#include "op-i386.h"
112

    
113
/* operand size */
114
enum {
115
    OT_BYTE = 0,
116
    OT_WORD,
117
    OT_LONG, 
118
    OT_QUAD,
119
};
120

    
121
enum {
122
    /* I386 int registers */
123
    OR_EAX,   /* MUST be even numbered */
124
    OR_ECX,
125
    OR_EDX,
126
    OR_EBX,
127
    OR_ESP,
128
    OR_EBP,
129
    OR_ESI,
130
    OR_EDI,
131
    OR_TMP0,    /* temporary operand register */
132
    OR_TMP1,
133
    OR_A0, /* temporary register used when doing address evaluation */
134
    OR_ZERO, /* fixed zero register */
135
    NB_OREGS,
136
};
137

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

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

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

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

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

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

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

    
366
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
367
    [OT_BYTE] = {
368
        gen_op_adcb_T0_T1_cc,
369
        gen_op_sbbb_T0_T1_cc,
370
    },
371
    [OT_WORD] = {
372
        gen_op_adcw_T0_T1_cc,
373
        gen_op_sbbw_T0_T1_cc,
374
    },
375
    [OT_LONG] = {
376
        gen_op_adcl_T0_T1_cc,
377
        gen_op_sbbl_T0_T1_cc,
378
    },
379
};
380

    
381
static const int cc_op_arithb[8] = {
382
    CC_OP_ADDB,
383
    CC_OP_LOGICB,
384
    CC_OP_ADDB,
385
    CC_OP_SUBB,
386
    CC_OP_LOGICB,
387
    CC_OP_SUBB,
388
    CC_OP_LOGICB,
389
    CC_OP_SUBB,
390
};
391

    
392
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
393
    gen_op_cmpxchgb_T0_T1_EAX_cc,
394
    gen_op_cmpxchgw_T0_T1_EAX_cc,
395
    gen_op_cmpxchgl_T0_T1_EAX_cc,
396
};
397

    
398
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
399
    [OT_BYTE] = {
400
        gen_op_rolb_T0_T1_cc,
401
        gen_op_rorb_T0_T1_cc,
402
        gen_op_rclb_T0_T1_cc,
403
        gen_op_rcrb_T0_T1_cc,
404
        gen_op_shlb_T0_T1_cc,
405
        gen_op_shrb_T0_T1_cc,
406
        gen_op_shlb_T0_T1_cc,
407
        gen_op_sarb_T0_T1_cc,
408
    },
409
    [OT_WORD] = {
410
        gen_op_rolw_T0_T1_cc,
411
        gen_op_rorw_T0_T1_cc,
412
        gen_op_rclw_T0_T1_cc,
413
        gen_op_rcrw_T0_T1_cc,
414
        gen_op_shlw_T0_T1_cc,
415
        gen_op_shrw_T0_T1_cc,
416
        gen_op_shlw_T0_T1_cc,
417
        gen_op_sarw_T0_T1_cc,
418
    },
419
    [OT_LONG] = {
420
        gen_op_roll_T0_T1_cc,
421
        gen_op_rorl_T0_T1_cc,
422
        gen_op_rcll_T0_T1_cc,
423
        gen_op_rcrl_T0_T1_cc,
424
        gen_op_shll_T0_T1_cc,
425
        gen_op_shrl_T0_T1_cc,
426
        gen_op_shll_T0_T1_cc,
427
        gen_op_sarl_T0_T1_cc,
428
    },
429
};
430

    
431
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
432
    [0] = {
433
        gen_op_shldw_T0_T1_im_cc,
434
        gen_op_shrdw_T0_T1_im_cc,
435
    },
436
    [1] = {
437
        gen_op_shldl_T0_T1_im_cc,
438
        gen_op_shrdl_T0_T1_im_cc,
439
    },
440
};
441

    
442
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
443
    [0] = {
444
        gen_op_shldw_T0_T1_ECX_cc,
445
        gen_op_shrdw_T0_T1_ECX_cc,
446
    },
447
    [1] = {
448
        gen_op_shldl_T0_T1_ECX_cc,
449
        gen_op_shrdl_T0_T1_ECX_cc,
450
    },
451
};
452

    
453
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
454
    [0] = {
455
        gen_op_btw_T0_T1_cc,
456
        gen_op_btsw_T0_T1_cc,
457
        gen_op_btrw_T0_T1_cc,
458
        gen_op_btcw_T0_T1_cc,
459
    },
460
    [1] = {
461
        gen_op_btl_T0_T1_cc,
462
        gen_op_btsl_T0_T1_cc,
463
        gen_op_btrl_T0_T1_cc,
464
        gen_op_btcl_T0_T1_cc,
465
    },
466
};
467

    
468
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
469
    [0] = {
470
        gen_op_bsfw_T0_cc,
471
        gen_op_bsrw_T0_cc,
472
    },
473
    [1] = {
474
        gen_op_bsfl_T0_cc,
475
        gen_op_bsrl_T0_cc,
476
    },
477
};
478

    
479
static GenOpFunc *gen_op_lds_T0_A0[3] = {
480
    gen_op_ldsb_T0_A0,
481
    gen_op_ldsw_T0_A0,
482
};
483

    
484
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
485
    gen_op_ldub_T0_A0,
486
    gen_op_lduw_T0_A0,
487
};
488

    
489
/* sign does not matter */
490
static GenOpFunc *gen_op_ld_T0_A0[3] = {
491
    gen_op_ldub_T0_A0,
492
    gen_op_lduw_T0_A0,
493
    gen_op_ldl_T0_A0,
494
};
495

    
496
static GenOpFunc *gen_op_ld_T1_A0[3] = {
497
    gen_op_ldub_T1_A0,
498
    gen_op_lduw_T1_A0,
499
    gen_op_ldl_T1_A0,
500
};
501

    
502
static GenOpFunc *gen_op_st_T0_A0[3] = {
503
    gen_op_stb_T0_A0,
504
    gen_op_stw_T0_A0,
505
    gen_op_stl_T0_A0,
506
};
507

    
508
static GenOpFunc *gen_op_movs[6] = {
509
    gen_op_movsb,
510
    gen_op_movsw,
511
    gen_op_movsl,
512
    gen_op_rep_movsb,
513
    gen_op_rep_movsw,
514
    gen_op_rep_movsl,
515
};
516

    
517
static GenOpFunc *gen_op_stos[6] = {
518
    gen_op_stosb,
519
    gen_op_stosw,
520
    gen_op_stosl,
521
    gen_op_rep_stosb,
522
    gen_op_rep_stosw,
523
    gen_op_rep_stosl,
524
};
525

    
526
static GenOpFunc *gen_op_lods[6] = {
527
    gen_op_lodsb,
528
    gen_op_lodsw,
529
    gen_op_lodsl,
530
    gen_op_rep_lodsb,
531
    gen_op_rep_lodsw,
532
    gen_op_rep_lodsl,
533
};
534

    
535
static GenOpFunc *gen_op_scas[9] = {
536
    gen_op_scasb,
537
    gen_op_scasw,
538
    gen_op_scasl,
539
    gen_op_repz_scasb,
540
    gen_op_repz_scasw,
541
    gen_op_repz_scasl,
542
    gen_op_repnz_scasb,
543
    gen_op_repnz_scasw,
544
    gen_op_repnz_scasl,
545
};
546

    
547
static GenOpFunc *gen_op_cmps[9] = {
548
    gen_op_cmpsb,
549
    gen_op_cmpsw,
550
    gen_op_cmpsl,
551
    gen_op_repz_cmpsb,
552
    gen_op_repz_cmpsw,
553
    gen_op_repz_cmpsl,
554
    gen_op_repnz_cmpsb,
555
    gen_op_repnz_cmpsw,
556
    gen_op_repnz_cmpsl,
557
};
558

    
559
static GenOpFunc *gen_op_ins[6] = {
560
    gen_op_insb,
561
    gen_op_insw,
562
    gen_op_insl,
563
    gen_op_rep_insb,
564
    gen_op_rep_insw,
565
    gen_op_rep_insl,
566
};
567

    
568

    
569
static GenOpFunc *gen_op_outs[6] = {
570
    gen_op_outsb,
571
    gen_op_outsw,
572
    gen_op_outsl,
573
    gen_op_rep_outsb,
574
    gen_op_rep_outsw,
575
    gen_op_rep_outsl,
576
};
577

    
578
static GenOpFunc *gen_op_in[3] = {
579
    gen_op_inb_T0_T1,
580
    gen_op_inw_T0_T1,
581
    gen_op_inl_T0_T1,
582
};
583

    
584
static GenOpFunc *gen_op_out[3] = {
585
    gen_op_outb_T0_T1,
586
    gen_op_outw_T0_T1,
587
    gen_op_outl_T0_T1,
588
};
589

    
590
enum {
591
    JCC_O,
592
    JCC_B,
593
    JCC_Z,
594
    JCC_BE,
595
    JCC_S,
596
    JCC_P,
597
    JCC_L,
598
    JCC_LE,
599
};
600

    
601
static GenOpFunc2 *gen_jcc_slow[8] = {
602
    gen_op_jo_cc,
603
    gen_op_jb_cc,
604
    gen_op_jz_cc,
605
    gen_op_jbe_cc,
606
    gen_op_js_cc,
607
    gen_op_jp_cc,
608
    gen_op_jl_cc,
609
    gen_op_jle_cc,
610
};
611
    
612
static GenOpFunc2 *gen_jcc_sub[3][8] = {
613
    [OT_BYTE] = {
614
        NULL,
615
        gen_op_jb_subb,
616
        gen_op_jz_subb,
617
        gen_op_jbe_subb,
618
        gen_op_js_subb,
619
        NULL,
620
        gen_op_jl_subb,
621
        gen_op_jle_subb,
622
    },
623
    [OT_WORD] = {
624
        NULL,
625
        gen_op_jb_subw,
626
        gen_op_jz_subw,
627
        gen_op_jbe_subw,
628
        gen_op_js_subw,
629
        NULL,
630
        gen_op_jl_subw,
631
        gen_op_jle_subw,
632
    },
633
    [OT_LONG] = {
634
        NULL,
635
        gen_op_jb_subl,
636
        gen_op_jz_subl,
637
        gen_op_jbe_subl,
638
        gen_op_js_subl,
639
        NULL,
640
        gen_op_jl_subl,
641
        gen_op_jle_subl,
642
    },
643
};
644
static GenOpFunc2 *gen_op_loop[2][4] = {
645
    [0] = {
646
        gen_op_loopnzw,
647
        gen_op_loopzw,
648
        gen_op_loopw,
649
        gen_op_jecxzw,
650
    },
651
    [1] = {
652
        gen_op_loopnzl,
653
        gen_op_loopzl,
654
        gen_op_loopl,
655
        gen_op_jecxzl,
656
    },
657
};
658

    
659
static GenOpFunc *gen_setcc_slow[8] = {
660
    gen_op_seto_T0_cc,
661
    gen_op_setb_T0_cc,
662
    gen_op_setz_T0_cc,
663
    gen_op_setbe_T0_cc,
664
    gen_op_sets_T0_cc,
665
    gen_op_setp_T0_cc,
666
    gen_op_setl_T0_cc,
667
    gen_op_setle_T0_cc,
668
};
669

    
670
static GenOpFunc *gen_setcc_sub[3][8] = {
671
    [OT_BYTE] = {
672
        NULL,
673
        gen_op_setb_T0_subb,
674
        gen_op_setz_T0_subb,
675
        gen_op_setbe_T0_subb,
676
        gen_op_sets_T0_subb,
677
        NULL,
678
        gen_op_setl_T0_subb,
679
        gen_op_setle_T0_subb,
680
    },
681
    [OT_WORD] = {
682
        NULL,
683
        gen_op_setb_T0_subw,
684
        gen_op_setz_T0_subw,
685
        gen_op_setbe_T0_subw,
686
        gen_op_sets_T0_subw,
687
        NULL,
688
        gen_op_setl_T0_subw,
689
        gen_op_setle_T0_subw,
690
    },
691
    [OT_LONG] = {
692
        NULL,
693
        gen_op_setb_T0_subl,
694
        gen_op_setz_T0_subl,
695
        gen_op_setbe_T0_subl,
696
        gen_op_sets_T0_subl,
697
        NULL,
698
        gen_op_setl_T0_subl,
699
        gen_op_setle_T0_subl,
700
    },
701
};
702

    
703
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
704
    gen_op_fadd_ST0_FT0,
705
    gen_op_fmul_ST0_FT0,
706
    gen_op_fcom_ST0_FT0,
707
    gen_op_fcom_ST0_FT0,
708
    gen_op_fsub_ST0_FT0,
709
    gen_op_fsubr_ST0_FT0,
710
    gen_op_fdiv_ST0_FT0,
711
    gen_op_fdivr_ST0_FT0,
712
};
713

    
714
/* NOTE the exception in "r" op ordering */
715
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
716
    gen_op_fadd_STN_ST0,
717
    gen_op_fmul_STN_ST0,
718
    NULL,
719
    NULL,
720
    gen_op_fsubr_STN_ST0,
721
    gen_op_fsub_STN_ST0,
722
    gen_op_fdivr_STN_ST0,
723
    gen_op_fdiv_STN_ST0,
724
};
725

    
726
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
727
{
728
    if (d != OR_TMP0)
729
        gen_op_mov_TN_reg[ot][0][d]();
730
    if (s != OR_TMP1)
731
        gen_op_mov_TN_reg[ot][1][s]();
732
    if (op == OP_ADCL || op == OP_SBBL) {
733
        if (s1->cc_op != CC_OP_DYNAMIC)
734
            gen_op_set_cc_op(s1->cc_op);
735
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
736
        s1->cc_op = CC_OP_DYNAMIC;
737
    } else {
738
        gen_op_arith_T0_T1_cc[op]();
739
        s1->cc_op = cc_op_arithb[op] + ot;
740
    }
741
    if (d != OR_TMP0 && op != OP_CMPL)
742
        gen_op_mov_reg_T0[ot][d]();
743
}
744

    
745
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
746
{
747
    gen_op_movl_T1_im(c);
748
    gen_op(s1, op, ot, d, OR_TMP1);
749
}
750

    
751
static void gen_inc(DisasContext *s1, int ot, int d, int c)
752
{
753
    if (d != OR_TMP0)
754
        gen_op_mov_TN_reg[ot][0][d]();
755
    if (s1->cc_op != CC_OP_DYNAMIC)
756
        gen_op_set_cc_op(s1->cc_op);
757
    if (c > 0) {
758
        gen_op_incl_T0_cc();
759
        s1->cc_op = CC_OP_INCB + ot;
760
    } else {
761
        gen_op_decl_T0_cc();
762
        s1->cc_op = CC_OP_DECB + ot;
763
    }
764
    if (d != OR_TMP0)
765
        gen_op_mov_reg_T0[ot][d]();
766
}
767

    
768
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
769
{
770
    if (d != OR_TMP0)
771
        gen_op_mov_TN_reg[ot][0][d]();
772
    if (s != OR_TMP1)
773
        gen_op_mov_TN_reg[ot][1][s]();
774
    /* for zero counts, flags are not updated, so must do it dynamically */
775
    if (s1->cc_op != CC_OP_DYNAMIC)
776
        gen_op_set_cc_op(s1->cc_op);
777

    
778
    gen_op_shift_T0_T1_cc[ot][op]();
779

    
780
    if (d != OR_TMP0)
781
        gen_op_mov_reg_T0[ot][d]();
782
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
783
}
784

    
785
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
786
{
787
    /* currently not optimized */
788
    gen_op_movl_T1_im(c);
789
    gen_shift(s1, op, ot, d, OR_TMP1);
790
}
791

    
792
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
793
{
794
    int havesib;
795
    int base, disp;
796
    int index;
797
    int scale;
798
    int opreg;
799
    int mod, rm, code, override, must_add_seg;
800

    
801
    /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
802
    override = -1;
803
    must_add_seg = s->addseg;
804
    if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | 
805
                     PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
806
        if (s->prefix & PREFIX_ES)
807
            override = R_ES;
808
        else if (s->prefix & PREFIX_CS)
809
            override = R_CS;
810
        else if (s->prefix & PREFIX_SS)
811
            override = R_SS;
812
        else if (s->prefix & PREFIX_DS)
813
            override = R_DS;
814
        else if (s->prefix & PREFIX_FS)
815
            override = R_FS;
816
        else
817
            override = R_GS;
818
        must_add_seg = 1;
819
    }
820

    
821
    mod = (modrm >> 6) & 3;
822
    rm = modrm & 7;
823

    
824
    if (s->aflag) {
825

    
826
        havesib = 0;
827
        base = rm;
828
        index = 0;
829
        scale = 0;
830
        
831
        if (base == 4) {
832
            havesib = 1;
833
            code = ldub(s->pc++);
834
            scale = (code >> 6) & 3;
835
            index = (code >> 3) & 7;
836
            base = code & 7;
837
        }
838

    
839
        switch (mod) {
840
        case 0:
841
            if (base == 5) {
842
                base = -1;
843
                disp = ldl(s->pc);
844
                s->pc += 4;
845
            } else {
846
                disp = 0;
847
            }
848
            break;
849
        case 1:
850
            disp = (int8_t)ldub(s->pc++);
851
            break;
852
        default:
853
        case 2:
854
            disp = ldl(s->pc);
855
            s->pc += 4;
856
            break;
857
        }
858
        
859
        if (base >= 0) {
860
            gen_op_movl_A0_reg[base]();
861
            if (disp != 0)
862
                gen_op_addl_A0_im(disp);
863
        } else {
864
            gen_op_movl_A0_im(disp);
865
        }
866
        if (havesib && (index != 4 || scale != 0)) {
867
            gen_op_addl_A0_reg_sN[scale][index]();
868
        }
869
        if (must_add_seg) {
870
            if (override < 0) {
871
                if (base == R_EBP || base == R_ESP)
872
                    override = R_SS;
873
                else
874
                    override = R_DS;
875
            }
876
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
877
        }
878
    } else {
879
        switch (mod) {
880
        case 0:
881
            if (rm == 6) {
882
                disp = lduw(s->pc);
883
                s->pc += 2;
884
                gen_op_movl_A0_im(disp);
885
                rm = 0; /* avoid SS override */
886
                goto no_rm;
887
            } else {
888
                disp = 0;
889
            }
890
            break;
891
        case 1:
892
            disp = (int8_t)ldub(s->pc++);
893
            break;
894
        default:
895
        case 2:
896
            disp = lduw(s->pc);
897
            s->pc += 2;
898
            break;
899
        }
900
        switch(rm) {
901
        case 0:
902
            gen_op_movl_A0_reg[R_EBX]();
903
            gen_op_addl_A0_reg_sN[0][R_ESI]();
904
            break;
905
        case 1:
906
            gen_op_movl_A0_reg[R_EBX]();
907
            gen_op_addl_A0_reg_sN[0][R_EDI]();
908
            break;
909
        case 2:
910
            gen_op_movl_A0_reg[R_EBP]();
911
            gen_op_addl_A0_reg_sN[0][R_ESI]();
912
            break;
913
        case 3:
914
            gen_op_movl_A0_reg[R_EBP]();
915
            gen_op_addl_A0_reg_sN[0][R_EDI]();
916
            break;
917
        case 4:
918
            gen_op_movl_A0_reg[R_ESI]();
919
            break;
920
        case 5:
921
            gen_op_movl_A0_reg[R_EDI]();
922
            break;
923
        case 6:
924
            gen_op_movl_A0_reg[R_EBP]();
925
            break;
926
        default:
927
        case 7:
928
            gen_op_movl_A0_reg[R_EBX]();
929
            break;
930
        }
931
        if (disp != 0)
932
            gen_op_addl_A0_im(disp);
933
        gen_op_andl_A0_ffff();
934
    no_rm:
935
        if (must_add_seg) {
936
            if (override < 0) {
937
                if (rm == 2 || rm == 3 || rm == 6)
938
                    override = R_SS;
939
                else
940
                    override = R_DS;
941
            }
942
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
943
        }
944
    }
945

    
946
    opreg = OR_A0;
947
    disp = 0;
948
    *reg_ptr = opreg;
949
    *offset_ptr = disp;
950
}
951

    
952
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
953
   OR_TMP0 */
954
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
955
{
956
    int mod, rm, opreg, disp;
957

    
958
    mod = (modrm >> 6) & 3;
959
    rm = modrm & 7;
960
    if (mod == 3) {
961
        if (is_store) {
962
            if (reg != OR_TMP0)
963
                gen_op_mov_TN_reg[ot][0][reg]();
964
            gen_op_mov_reg_T0[ot][rm]();
965
        } else {
966
            gen_op_mov_TN_reg[ot][0][rm]();
967
            if (reg != OR_TMP0)
968
                gen_op_mov_reg_T0[ot][reg]();
969
        }
970
    } else {
971
        gen_lea_modrm(s, modrm, &opreg, &disp);
972
        if (is_store) {
973
            if (reg != OR_TMP0)
974
                gen_op_mov_TN_reg[ot][0][reg]();
975
            gen_op_st_T0_A0[ot]();
976
        } else {
977
            gen_op_ld_T0_A0[ot]();
978
            if (reg != OR_TMP0)
979
                gen_op_mov_reg_T0[ot][reg]();
980
        }
981
    }
982
}
983

    
984
static inline uint32_t insn_get(DisasContext *s, int ot)
985
{
986
    uint32_t ret;
987

    
988
    switch(ot) {
989
    case OT_BYTE:
990
        ret = ldub(s->pc);
991
        s->pc++;
992
        break;
993
    case OT_WORD:
994
        ret = lduw(s->pc);
995
        s->pc += 2;
996
        break;
997
    default:
998
    case OT_LONG:
999
        ret = ldl(s->pc);
1000
        s->pc += 4;
1001
        break;
1002
    }
1003
    return ret;
1004
}
1005

    
1006
static void gen_jcc(DisasContext *s, int b, int val)
1007
{
1008
    int inv, jcc_op;
1009
    GenOpFunc2 *func;
1010

    
1011
    inv = b & 1;
1012
    jcc_op = (b >> 1) & 7;
1013
    switch(s->cc_op) {
1014
        /* we optimize the cmp/jcc case */
1015
    case CC_OP_SUBB:
1016
    case CC_OP_SUBW:
1017
    case CC_OP_SUBL:
1018
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1019
        if (!func)
1020
            goto slow_jcc;
1021
        break;
1022
        
1023
        /* some jumps are easy to compute */
1024
    case CC_OP_ADDB:
1025
    case CC_OP_ADDW:
1026
    case CC_OP_ADDL:
1027
    case CC_OP_ADCB:
1028
    case CC_OP_ADCW:
1029
    case CC_OP_ADCL:
1030
    case CC_OP_SBBB:
1031
    case CC_OP_SBBW:
1032
    case CC_OP_SBBL:
1033
    case CC_OP_LOGICB:
1034
    case CC_OP_LOGICW:
1035
    case CC_OP_LOGICL:
1036
    case CC_OP_INCB:
1037
    case CC_OP_INCW:
1038
    case CC_OP_INCL:
1039
    case CC_OP_DECB:
1040
    case CC_OP_DECW:
1041
    case CC_OP_DECL:
1042
    case CC_OP_SHLB:
1043
    case CC_OP_SHLW:
1044
    case CC_OP_SHLL:
1045
    case CC_OP_SARB:
1046
    case CC_OP_SARW:
1047
    case CC_OP_SARL:
1048
        switch(jcc_op) {
1049
        case JCC_Z:
1050
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1051
            break;
1052
        case JCC_S:
1053
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1054
            break;
1055
        default:
1056
            goto slow_jcc;
1057
        }
1058
        break;
1059
    default:
1060
    slow_jcc:
1061
        if (s->cc_op != CC_OP_DYNAMIC)
1062
            gen_op_set_cc_op(s->cc_op);
1063
        func = gen_jcc_slow[jcc_op];
1064
        break;
1065
    }
1066
    if (!inv) {
1067
        func(val, (long)s->pc);
1068
    } else {
1069
        func((long)s->pc, val);
1070
    }
1071
}
1072

    
1073
static void gen_setcc(DisasContext *s, int b)
1074
{
1075
    int inv, jcc_op;
1076
    GenOpFunc *func;
1077

    
1078
    inv = b & 1;
1079
    jcc_op = (b >> 1) & 7;
1080
    switch(s->cc_op) {
1081
        /* we optimize the cmp/jcc case */
1082
    case CC_OP_SUBB:
1083
    case CC_OP_SUBW:
1084
    case CC_OP_SUBL:
1085
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1086
        if (!func)
1087
            goto slow_jcc;
1088
        break;
1089
        
1090
        /* some jumps are easy to compute */
1091
    case CC_OP_ADDB:
1092
    case CC_OP_ADDW:
1093
    case CC_OP_ADDL:
1094
    case CC_OP_LOGICB:
1095
    case CC_OP_LOGICW:
1096
    case CC_OP_LOGICL:
1097
    case CC_OP_INCB:
1098
    case CC_OP_INCW:
1099
    case CC_OP_INCL:
1100
    case CC_OP_DECB:
1101
    case CC_OP_DECW:
1102
    case CC_OP_DECL:
1103
    case CC_OP_SHLB:
1104
    case CC_OP_SHLW:
1105
    case CC_OP_SHLL:
1106
        switch(jcc_op) {
1107
        case JCC_Z:
1108
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1109
            break;
1110
        case JCC_S:
1111
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1112
            break;
1113
        default:
1114
            goto slow_jcc;
1115
        }
1116
        break;
1117
    default:
1118
    slow_jcc:
1119
        if (s->cc_op != CC_OP_DYNAMIC)
1120
            gen_op_set_cc_op(s->cc_op);
1121
        func = gen_setcc_slow[jcc_op];
1122
        break;
1123
    }
1124
    func();
1125
    if (inv) {
1126
        gen_op_xor_T0_1();
1127
    }
1128
}
1129

    
1130
/* move T0 to seg_reg and compute if the CPU state may change */
1131
void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1132
{
1133
    gen_op_movl_seg_T0(seg_reg);
1134
    if (!s->addseg && seg_reg < R_FS)
1135
        s->is_jmp = 2; /* abort translation because the register may
1136
                          have a non zero base */
1137
}
1138

    
1139
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1140
   is set to true if the instruction sets the PC (last instruction of
1141
   a basic block) */
1142
long disas_insn(DisasContext *s, uint8_t *pc_start)
1143
{
1144
    int b, prefixes, aflag, dflag;
1145
    int shift, ot;
1146
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1147

    
1148
    s->pc = pc_start;
1149
    prefixes = 0;
1150
    aflag = s->code32;
1151
    dflag = s->code32;
1152
    //    cur_pc = s->pc; /* for insn generation */
1153
 next_byte:
1154
    b = ldub(s->pc);
1155
    s->pc++;
1156
    /* check prefixes */
1157
    switch (b) {
1158
    case 0xf3:
1159
        prefixes |= PREFIX_REPZ;
1160
        goto next_byte;
1161
    case 0xf2:
1162
        prefixes |= PREFIX_REPNZ;
1163
        goto next_byte;
1164
    case 0xf0:
1165
        prefixes |= PREFIX_LOCK;
1166
        goto next_byte;
1167
    case 0x2e:
1168
        prefixes |= PREFIX_CS;
1169
        goto next_byte;
1170
    case 0x36:
1171
        prefixes |= PREFIX_SS;
1172
        goto next_byte;
1173
    case 0x3e:
1174
        prefixes |= PREFIX_DS;
1175
        goto next_byte;
1176
    case 0x26:
1177
        prefixes |= PREFIX_ES;
1178
        goto next_byte;
1179
    case 0x64:
1180
        prefixes |= PREFIX_FS;
1181
        goto next_byte;
1182
    case 0x65:
1183
        prefixes |= PREFIX_GS;
1184
        goto next_byte;
1185
    case 0x66:
1186
        prefixes |= PREFIX_DATA;
1187
        goto next_byte;
1188
    case 0x67:
1189
        prefixes |= PREFIX_ADR;
1190
        goto next_byte;
1191
    case 0x9b:
1192
        prefixes |= PREFIX_FWAIT;
1193
        goto next_byte;
1194
    }
1195

    
1196
    if (prefixes & PREFIX_DATA)
1197
        dflag ^= 1;
1198
    if (prefixes & PREFIX_ADR)
1199
        aflag ^= 1;
1200

    
1201
    s->prefix = prefixes;
1202
    s->aflag = aflag;
1203
    s->dflag = dflag;
1204

    
1205
    /* now check op code */
1206
 reswitch:
1207
    switch(b) {
1208
    case 0x0f:
1209
        /**************************/
1210
        /* extended op code */
1211
        b = ldub(s->pc++) | 0x100;
1212
        goto reswitch;
1213
        
1214
        /**************************/
1215
        /* arith & logic */
1216
    case 0x00 ... 0x05:
1217
    case 0x08 ... 0x0d:
1218
    case 0x10 ... 0x15:
1219
    case 0x18 ... 0x1d:
1220
    case 0x20 ... 0x25:
1221
    case 0x28 ... 0x2d:
1222
    case 0x30 ... 0x35:
1223
    case 0x38 ... 0x3d:
1224
        {
1225
            int op, f, val;
1226
            op = (b >> 3) & 7;
1227
            f = (b >> 1) & 3;
1228

    
1229
            if ((b & 1) == 0)
1230
                ot = OT_BYTE;
1231
            else
1232
                ot = dflag ? OT_LONG : OT_WORD;
1233
            
1234
            switch(f) {
1235
            case 0: /* OP Ev, Gv */
1236
                modrm = ldub(s->pc++);
1237
                reg = ((modrm >> 3) & 7) + OR_EAX;
1238
                mod = (modrm >> 6) & 3;
1239
                rm = modrm & 7;
1240
                if (mod != 3) {
1241
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1242
                    gen_op_ld_T0_A0[ot]();
1243
                    opreg = OR_TMP0;
1244
                } else {
1245
                    opreg = OR_EAX + rm;
1246
                }
1247
                gen_op(s, op, ot, opreg, reg);
1248
                if (mod != 3 && op != 7) {
1249
                    gen_op_st_T0_A0[ot]();
1250
                }
1251
                break;
1252
            case 1: /* OP Gv, Ev */
1253
                modrm = ldub(s->pc++);
1254
                mod = (modrm >> 6) & 3;
1255
                reg = ((modrm >> 3) & 7) + OR_EAX;
1256
                rm = modrm & 7;
1257
                if (mod != 3) {
1258
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1259
                    gen_op_ld_T1_A0[ot]();
1260
                    opreg = OR_TMP1;
1261
                } else {
1262
                    opreg = OR_EAX + rm;
1263
                }
1264
                gen_op(s, op, ot, reg, opreg);
1265
                break;
1266
            case 2: /* OP A, Iv */
1267
                val = insn_get(s, ot);
1268
                gen_opi(s, op, ot, OR_EAX, val);
1269
                break;
1270
            }
1271
        }
1272
        break;
1273

    
1274
    case 0x80: /* GRP1 */
1275
    case 0x81:
1276
    case 0x83:
1277
        {
1278
            int val;
1279

    
1280
            if ((b & 1) == 0)
1281
                ot = OT_BYTE;
1282
            else
1283
                ot = dflag ? OT_LONG : OT_WORD;
1284
            
1285
            modrm = ldub(s->pc++);
1286
            mod = (modrm >> 6) & 3;
1287
            rm = modrm & 7;
1288
            op = (modrm >> 3) & 7;
1289
            
1290
            if (mod != 3) {
1291
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1292
                gen_op_ld_T0_A0[ot]();
1293
                opreg = OR_TMP0;
1294
            } else {
1295
                opreg = rm + OR_EAX;
1296
            }
1297

    
1298
            switch(b) {
1299
            default:
1300
            case 0x80:
1301
            case 0x81:
1302
                val = insn_get(s, ot);
1303
                break;
1304
            case 0x83:
1305
                val = (int8_t)insn_get(s, OT_BYTE);
1306
                break;
1307
            }
1308

    
1309
            gen_opi(s, op, ot, opreg, val);
1310
            if (op != 7 && mod != 3) {
1311
                gen_op_st_T0_A0[ot]();
1312
            }
1313
        }
1314
        break;
1315

    
1316
        /**************************/
1317
        /* inc, dec, and other misc arith */
1318
    case 0x40 ... 0x47: /* inc Gv */
1319
        ot = dflag ? OT_LONG : OT_WORD;
1320
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1321
        break;
1322
    case 0x48 ... 0x4f: /* dec Gv */
1323
        ot = dflag ? OT_LONG : OT_WORD;
1324
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1325
        break;
1326
    case 0xf6: /* GRP3 */
1327
    case 0xf7:
1328
        if ((b & 1) == 0)
1329
            ot = OT_BYTE;
1330
        else
1331
            ot = dflag ? OT_LONG : OT_WORD;
1332

    
1333
        modrm = ldub(s->pc++);
1334
        mod = (modrm >> 6) & 3;
1335
        rm = modrm & 7;
1336
        op = (modrm >> 3) & 7;
1337
        if (mod != 3) {
1338
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1339
            gen_op_ld_T0_A0[ot]();
1340
        } else {
1341
            gen_op_mov_TN_reg[ot][0][rm]();
1342
        }
1343

    
1344
        switch(op) {
1345
        case 0: /* test */
1346
            val = insn_get(s, ot);
1347
            gen_op_movl_T1_im(val);
1348
            gen_op_testl_T0_T1_cc();
1349
            s->cc_op = CC_OP_LOGICB + ot;
1350
            break;
1351
        case 2: /* not */
1352
            gen_op_notl_T0();
1353
            if (mod != 3) {
1354
                gen_op_st_T0_A0[ot]();
1355
            } else {
1356
                gen_op_mov_reg_T0[ot][rm]();
1357
            }
1358
            break;
1359
        case 3: /* neg */
1360
            gen_op_negl_T0_cc();
1361
            if (mod != 3) {
1362
                gen_op_st_T0_A0[ot]();
1363
            } else {
1364
                gen_op_mov_reg_T0[ot][rm]();
1365
            }
1366
            s->cc_op = CC_OP_SUBB + ot;
1367
            break;
1368
        case 4: /* mul */
1369
            switch(ot) {
1370
            case OT_BYTE:
1371
                gen_op_mulb_AL_T0();
1372
                break;
1373
            case OT_WORD:
1374
                gen_op_mulw_AX_T0();
1375
                break;
1376
            default:
1377
            case OT_LONG:
1378
                gen_op_mull_EAX_T0();
1379
                break;
1380
            }
1381
            s->cc_op = CC_OP_MUL;
1382
            break;
1383
        case 5: /* imul */
1384
            switch(ot) {
1385
            case OT_BYTE:
1386
                gen_op_imulb_AL_T0();
1387
                break;
1388
            case OT_WORD:
1389
                gen_op_imulw_AX_T0();
1390
                break;
1391
            default:
1392
            case OT_LONG:
1393
                gen_op_imull_EAX_T0();
1394
                break;
1395
            }
1396
            s->cc_op = CC_OP_MUL;
1397
            break;
1398
        case 6: /* div */
1399
            switch(ot) {
1400
            case OT_BYTE:
1401
                gen_op_divb_AL_T0();
1402
                break;
1403
            case OT_WORD:
1404
                gen_op_divw_AX_T0();
1405
                break;
1406
            default:
1407
            case OT_LONG:
1408
                gen_op_divl_EAX_T0();
1409
                break;
1410
            }
1411
            break;
1412
        case 7: /* idiv */
1413
            switch(ot) {
1414
            case OT_BYTE:
1415
                gen_op_idivb_AL_T0();
1416
                break;
1417
            case OT_WORD:
1418
                gen_op_idivw_AX_T0();
1419
                break;
1420
            default:
1421
            case OT_LONG:
1422
                gen_op_idivl_EAX_T0();
1423
                break;
1424
            }
1425
            break;
1426
        default:
1427
            goto illegal_op;
1428
        }
1429
        break;
1430

    
1431
    case 0xfe: /* GRP4 */
1432
    case 0xff: /* GRP5 */
1433
        if ((b & 1) == 0)
1434
            ot = OT_BYTE;
1435
        else
1436
            ot = dflag ? OT_LONG : OT_WORD;
1437

    
1438
        modrm = ldub(s->pc++);
1439
        mod = (modrm >> 6) & 3;
1440
        rm = modrm & 7;
1441
        op = (modrm >> 3) & 7;
1442
        if (op >= 2 && b == 0xfe) {
1443
            goto illegal_op;
1444
        }
1445
        if (mod != 3) {
1446
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1447
            gen_op_ld_T0_A0[ot]();
1448
        } else {
1449
            gen_op_mov_TN_reg[ot][0][rm]();
1450
        }
1451

    
1452
        switch(op) {
1453
        case 0: /* inc Ev */
1454
            gen_inc(s, ot, OR_TMP0, 1);
1455
            if (mod != 3)
1456
                gen_op_st_T0_A0[ot]();
1457
            else
1458
                gen_op_mov_reg_T0[ot][rm]();
1459
            break;
1460
        case 1: /* dec Ev */
1461
            gen_inc(s, ot, OR_TMP0, -1);
1462
            if (mod != 3)
1463
                gen_op_st_T0_A0[ot]();
1464
            else
1465
                gen_op_mov_reg_T0[ot][rm]();
1466
            break;
1467
        case 2: /* call Ev */
1468
            gen_op_movl_T1_im((long)s->pc);
1469
            gen_op_pushl_T1();
1470
            gen_op_jmp_T0();
1471
            s->is_jmp = 1;
1472
            break;
1473
        case 4: /* jmp Ev */
1474
            gen_op_jmp_T0();
1475
            s->is_jmp = 1;
1476
            break;
1477
        case 6: /* push Ev */
1478
            gen_op_pushl_T0();
1479
            break;
1480
        default:
1481
            goto illegal_op;
1482
        }
1483
        break;
1484

    
1485
    case 0x84: /* test Ev, Gv */
1486
    case 0x85: 
1487
        if ((b & 1) == 0)
1488
            ot = OT_BYTE;
1489
        else
1490
            ot = dflag ? OT_LONG : OT_WORD;
1491

    
1492
        modrm = ldub(s->pc++);
1493
        mod = (modrm >> 6) & 3;
1494
        rm = modrm & 7;
1495
        reg = (modrm >> 3) & 7;
1496
        
1497
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1498
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1499
        gen_op_testl_T0_T1_cc();
1500
        s->cc_op = CC_OP_LOGICB + ot;
1501
        break;
1502
        
1503
    case 0xa8: /* test eAX, Iv */
1504
    case 0xa9:
1505
        if ((b & 1) == 0)
1506
            ot = OT_BYTE;
1507
        else
1508
            ot = dflag ? OT_LONG : OT_WORD;
1509
        val = insn_get(s, ot);
1510

    
1511
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1512
        gen_op_movl_T1_im(val);
1513
        gen_op_testl_T0_T1_cc();
1514
        s->cc_op = CC_OP_LOGICB + ot;
1515
        break;
1516
        
1517
    case 0x98: /* CWDE/CBW */
1518
        if (dflag)
1519
            gen_op_movswl_EAX_AX();
1520
        else
1521
            gen_op_movsbw_AX_AL();
1522
        break;
1523
    case 0x99: /* CDQ/CWD */
1524
        if (dflag)
1525
            gen_op_movslq_EDX_EAX();
1526
        else
1527
            gen_op_movswl_DX_AX();
1528
        break;
1529
    case 0x1af: /* imul Gv, Ev */
1530
    case 0x69: /* imul Gv, Ev, I */
1531
    case 0x6b:
1532
        ot = dflag ? OT_LONG : OT_WORD;
1533
        modrm = ldub(s->pc++);
1534
        reg = ((modrm >> 3) & 7) + OR_EAX;
1535
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1536
        if (b == 0x69) {
1537
            val = insn_get(s, ot);
1538
            gen_op_movl_T1_im(val);
1539
        } else if (b == 0x6b) {
1540
            val = insn_get(s, OT_BYTE);
1541
            gen_op_movl_T1_im(val);
1542
        } else {
1543
            gen_op_mov_TN_reg[ot][1][reg]();
1544
        }
1545

    
1546
        if (ot == OT_LONG) {
1547
            gen_op_imull_T0_T1();
1548
        } else {
1549
            gen_op_imulw_T0_T1();
1550
        }
1551
        gen_op_mov_reg_T0[ot][reg]();
1552
        s->cc_op = CC_OP_MUL;
1553
        break;
1554
    case 0x1c0:
1555
    case 0x1c1: /* xadd Ev, Gv */
1556
        if ((b & 1) == 0)
1557
            ot = OT_BYTE;
1558
        else
1559
            ot = dflag ? OT_LONG : OT_WORD;
1560
        modrm = ldub(s->pc++);
1561
        reg = (modrm >> 3) & 7;
1562
        mod = (modrm >> 6) & 3;
1563
        if (mod == 3) {
1564
            rm = modrm & 7;
1565
            gen_op_mov_TN_reg[ot][0][reg]();
1566
            gen_op_mov_TN_reg[ot][1][rm]();
1567
            gen_op_addl_T0_T1_cc();
1568
            gen_op_mov_reg_T0[ot][rm]();
1569
            gen_op_mov_reg_T1[ot][reg]();
1570
        } else {
1571
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1572
            gen_op_mov_TN_reg[ot][0][reg]();
1573
            gen_op_ld_T1_A0[ot]();
1574
            gen_op_addl_T0_T1_cc();
1575
            gen_op_st_T0_A0[ot]();
1576
            gen_op_mov_reg_T1[ot][reg]();
1577
        }
1578
        s->cc_op = CC_OP_ADDB + ot;
1579
        break;
1580
    case 0x1b0:
1581
    case 0x1b1: /* cmpxchg Ev, Gv */
1582
        if ((b & 1) == 0)
1583
            ot = OT_BYTE;
1584
        else
1585
            ot = dflag ? OT_LONG : OT_WORD;
1586
        modrm = ldub(s->pc++);
1587
        reg = (modrm >> 3) & 7;
1588
        mod = (modrm >> 6) & 3;
1589
        gen_op_mov_TN_reg[ot][1][reg]();
1590
        if (mod == 3) {
1591
            rm = modrm & 7;
1592
            gen_op_mov_TN_reg[ot][0][rm]();
1593
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1594
            gen_op_mov_reg_T0[ot][rm]();
1595
        } else {
1596
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1597
            gen_op_ld_T0_A0[ot]();
1598
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1599
            gen_op_st_T0_A0[ot]();
1600
        }
1601
        s->cc_op = CC_OP_SUBB + ot;
1602
        break;
1603
        
1604
        /**************************/
1605
        /* push/pop */
1606
    case 0x50 ... 0x57: /* push */
1607
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1608
        gen_op_pushl_T0();
1609
        break;
1610
    case 0x58 ... 0x5f: /* pop */
1611
        gen_op_popl_T0();
1612
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1613
        break;
1614
    case 0x60: /* pusha */
1615
        if (s->dflag)
1616
            gen_op_pushal();
1617
        else
1618
            gen_op_pushaw();
1619
        break;
1620
    case 0x61: /* popa */
1621
        if (s->dflag)
1622
            gen_op_popal();
1623
        else
1624
            gen_op_popaw();
1625
        break;
1626
    case 0x68: /* push Iv */
1627
    case 0x6a:
1628
        ot = dflag ? OT_LONG : OT_WORD;
1629
        if (b == 0x68)
1630
            val = insn_get(s, ot);
1631
        else
1632
            val = (int8_t)insn_get(s, OT_BYTE);
1633
        gen_op_movl_T0_im(val);
1634
        gen_op_pushl_T0();
1635
        break;
1636
    case 0x8f: /* pop Ev */
1637
        ot = dflag ? OT_LONG : OT_WORD;
1638
        modrm = ldub(s->pc++);
1639
        gen_op_popl_T0();
1640
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1641
        break;
1642
    case 0xc8: /* enter */
1643
        {
1644
            int level;
1645
            val = lduw(s->pc);
1646
            s->pc += 2;
1647
            level = ldub(s->pc++);
1648
            level &= 0x1f;
1649
            gen_op_enterl(val, level);
1650
        }
1651
        break;
1652
    case 0xc9: /* leave */
1653
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1654
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1655
        gen_op_popl_T0();
1656
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1657
        break;
1658
    case 0x06: /* push es */
1659
    case 0x0e: /* push cs */
1660
    case 0x16: /* push ss */
1661
    case 0x1e: /* push ds */
1662
        gen_op_movl_T0_seg(b >> 3);
1663
        gen_op_pushl_T0();
1664
        break;
1665
    case 0x1a0: /* push fs */
1666
    case 0x1a8: /* push gs */
1667
        gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1668
        gen_op_pushl_T0();
1669
        break;
1670
    case 0x07: /* pop es */
1671
    case 0x17: /* pop ss */
1672
    case 0x1f: /* pop ds */
1673
        gen_op_popl_T0();
1674
        gen_movl_seg_T0(s, b >> 3);
1675
        break;
1676
    case 0x1a1: /* pop fs */
1677
    case 0x1a9: /* pop gs */
1678
        gen_op_popl_T0();
1679
        gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1680
        break;
1681

    
1682
        /**************************/
1683
        /* mov */
1684
    case 0x88:
1685
    case 0x89: /* mov Gv, Ev */
1686
        if ((b & 1) == 0)
1687
            ot = OT_BYTE;
1688
        else
1689
            ot = dflag ? OT_LONG : OT_WORD;
1690
        modrm = ldub(s->pc++);
1691
        reg = (modrm >> 3) & 7;
1692
        
1693
        /* generate a generic store */
1694
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1695
        break;
1696
    case 0xc6:
1697
    case 0xc7: /* mov Ev, Iv */
1698
        if ((b & 1) == 0)
1699
            ot = OT_BYTE;
1700
        else
1701
            ot = dflag ? OT_LONG : OT_WORD;
1702
        modrm = ldub(s->pc++);
1703
        mod = (modrm >> 6) & 3;
1704
        if (mod != 3)
1705
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1706
        val = insn_get(s, ot);
1707
        gen_op_movl_T0_im(val);
1708
        if (mod != 3)
1709
            gen_op_st_T0_A0[ot]();
1710
        else
1711
            gen_op_mov_reg_T0[ot][modrm & 7]();
1712
        break;
1713
    case 0x8a:
1714
    case 0x8b: /* mov Ev, Gv */
1715
        if ((b & 1) == 0)
1716
            ot = OT_BYTE;
1717
        else
1718
            ot = dflag ? OT_LONG : OT_WORD;
1719
        modrm = ldub(s->pc++);
1720
        reg = (modrm >> 3) & 7;
1721
        
1722
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1723
        gen_op_mov_reg_T0[ot][reg]();
1724
        break;
1725
    case 0x8e: /* mov seg, Gv */
1726
        ot = dflag ? OT_LONG : OT_WORD;
1727
        modrm = ldub(s->pc++);
1728
        reg = (modrm >> 3) & 7;
1729
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1730
        if (reg >= 6)
1731
            goto illegal_op;
1732
        gen_movl_seg_T0(s, reg);
1733
        break;
1734
    case 0x8c: /* mov Gv, seg */
1735
        ot = dflag ? OT_LONG : OT_WORD;
1736
        modrm = ldub(s->pc++);
1737
        reg = (modrm >> 3) & 7;
1738
        if (reg >= 6)
1739
            goto illegal_op;
1740
        gen_op_movl_T0_seg(reg);
1741
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1742
        break;
1743

    
1744
    case 0x1b6: /* movzbS Gv, Eb */
1745
    case 0x1b7: /* movzwS Gv, Eb */
1746
    case 0x1be: /* movsbS Gv, Eb */
1747
    case 0x1bf: /* movswS Gv, Eb */
1748
        {
1749
            int d_ot;
1750
            /* d_ot is the size of destination */
1751
            d_ot = dflag + OT_WORD;
1752
            /* ot is the size of source */
1753
            ot = (b & 1) + OT_BYTE;
1754
            modrm = ldub(s->pc++);
1755
            reg = ((modrm >> 3) & 7) + OR_EAX;
1756
            mod = (modrm >> 6) & 3;
1757
            rm = modrm & 7;
1758
            
1759
            if (mod == 3) {
1760
                gen_op_mov_TN_reg[ot][0][rm]();
1761
                switch(ot | (b & 8)) {
1762
                case OT_BYTE:
1763
                    gen_op_movzbl_T0_T0();
1764
                    break;
1765
                case OT_BYTE | 8:
1766
                    gen_op_movsbl_T0_T0();
1767
                    break;
1768
                case OT_WORD:
1769
                    gen_op_movzwl_T0_T0();
1770
                    break;
1771
                default:
1772
                case OT_WORD | 8:
1773
                    gen_op_movswl_T0_T0();
1774
                    break;
1775
                }
1776
                gen_op_mov_reg_T0[d_ot][reg]();
1777
            } else {
1778
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1779
                if (b & 8) {
1780
                    gen_op_lds_T0_A0[ot]();
1781
                } else {
1782
                    gen_op_ldu_T0_A0[ot]();
1783
                }
1784
                gen_op_mov_reg_T0[d_ot][reg]();
1785
            }
1786
        }
1787
        break;
1788

    
1789
    case 0x8d: /* lea */
1790
        ot = dflag ? OT_LONG : OT_WORD;
1791
        modrm = ldub(s->pc++);
1792
        reg = (modrm >> 3) & 7;
1793
        /* we must ensure that no segment is added */
1794
        s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS | 
1795
                       PREFIX_ES | PREFIX_FS | PREFIX_GS);
1796
        val = s->addseg;
1797
        s->addseg = 0;
1798
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1799
        s->addseg = val;
1800
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1801
        break;
1802
        
1803
    case 0xa0: /* mov EAX, Ov */
1804
    case 0xa1:
1805
    case 0xa2: /* mov Ov, EAX */
1806
    case 0xa3:
1807
        if ((b & 1) == 0)
1808
            ot = OT_BYTE;
1809
        else
1810
            ot = dflag ? OT_LONG : OT_WORD;
1811
        if (s->aflag)
1812
            offset_addr = insn_get(s, OT_LONG);
1813
        else
1814
            offset_addr = insn_get(s, OT_WORD);
1815
        gen_op_movl_A0_im(offset_addr);
1816
        /* handle override */
1817
        /* XXX: factorize that */
1818
        {
1819
            int override, must_add_seg;
1820
            override = R_DS;
1821
            must_add_seg = s->addseg;
1822
            if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | 
1823
                             PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
1824
                if (s->prefix & PREFIX_ES)
1825
                    override = R_ES;
1826
                else if (s->prefix & PREFIX_CS)
1827
                    override = R_CS;
1828
                else if (s->prefix & PREFIX_SS)
1829
                    override = R_SS;
1830
                else if (s->prefix & PREFIX_DS)
1831
                    override = R_DS;
1832
                else if (s->prefix & PREFIX_FS)
1833
                    override = R_FS;
1834
                else
1835
                    override = R_GS;
1836
                must_add_seg = 1;
1837
            }
1838
            if (must_add_seg) {
1839
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1840
            }
1841
        }
1842
        if ((b & 2) == 0) {
1843
            gen_op_ld_T0_A0[ot]();
1844
            gen_op_mov_reg_T0[ot][R_EAX]();
1845
        } else {
1846
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1847
            gen_op_st_T0_A0[ot]();
1848
        }
1849
        break;
1850

    
1851
    case 0xb0 ... 0xb7: /* mov R, Ib */
1852
        val = insn_get(s, OT_BYTE);
1853
        gen_op_movl_T0_im(val);
1854
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1855
        break;
1856
    case 0xb8 ... 0xbf: /* mov R, Iv */
1857
        ot = dflag ? OT_LONG : OT_WORD;
1858
        val = insn_get(s, ot);
1859
        reg = OR_EAX + (b & 7);
1860
        gen_op_movl_T0_im(val);
1861
        gen_op_mov_reg_T0[ot][reg]();
1862
        break;
1863

    
1864
    case 0x91 ... 0x97: /* xchg R, EAX */
1865
        ot = dflag ? OT_LONG : OT_WORD;
1866
        reg = b & 7;
1867
        rm = R_EAX;
1868
        goto do_xchg_reg;
1869
    case 0x86:
1870
    case 0x87: /* xchg Ev, Gv */
1871
        if ((b & 1) == 0)
1872
            ot = OT_BYTE;
1873
        else
1874
            ot = dflag ? OT_LONG : OT_WORD;
1875
        modrm = ldub(s->pc++);
1876
        reg = (modrm >> 3) & 7;
1877
        mod = (modrm >> 6) & 3;
1878
        if (mod == 3) {
1879
            rm = modrm & 7;
1880
        do_xchg_reg:
1881
            gen_op_mov_TN_reg[ot][0][reg]();
1882
            gen_op_mov_TN_reg[ot][1][rm]();
1883
            gen_op_mov_reg_T0[ot][rm]();
1884
            gen_op_mov_reg_T1[ot][reg]();
1885
        } else {
1886
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1887
            gen_op_mov_TN_reg[ot][0][reg]();
1888
            gen_op_ld_T1_A0[ot]();
1889
            gen_op_st_T0_A0[ot]();
1890
            gen_op_mov_reg_T1[ot][reg]();
1891
        }
1892
        break;
1893
    case 0xc4: /* les Gv */
1894
        op = R_ES;
1895
        goto do_lxx;
1896
    case 0xc5: /* lds Gv */
1897
        op = R_DS;
1898
        goto do_lxx;
1899
    case 0x1b2: /* lss Gv */
1900
        op = R_SS;
1901
        goto do_lxx;
1902
    case 0x1b4: /* lfs Gv */
1903
        op = R_FS;
1904
        goto do_lxx;
1905
    case 0x1b5: /* lgs Gv */
1906
        op = R_GS;
1907
    do_lxx:
1908
        ot = dflag ? OT_LONG : OT_WORD;
1909
        modrm = ldub(s->pc++);
1910
        reg = (modrm >> 3) & 7;
1911
        mod = (modrm >> 6) & 3;
1912
        if (mod == 3)
1913
            goto illegal_op;
1914
        gen_op_ld_T1_A0[ot]();
1915
        op_addl_A0_im(1 << (ot - OT_WORD + 1));
1916
        /* load the segment first to handle exceptions properly */
1917
        gen_op_lduw_T0_A0();
1918
        gen_movl_seg_T0(s, op);
1919
        /* then put the data */
1920
        gen_op_mov_reg_T1[ot][reg]();
1921
        break;
1922
        
1923
        /************************/
1924
        /* shifts */
1925
    case 0xc0:
1926
    case 0xc1:
1927
        /* shift Ev,Ib */
1928
        shift = 2;
1929
    grp2:
1930
        {
1931
            if ((b & 1) == 0)
1932
                ot = OT_BYTE;
1933
            else
1934
                ot = dflag ? OT_LONG : OT_WORD;
1935
            
1936
            modrm = ldub(s->pc++);
1937
            mod = (modrm >> 6) & 3;
1938
            rm = modrm & 7;
1939
            op = (modrm >> 3) & 7;
1940
            
1941
            if (mod != 3) {
1942
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1943
                gen_op_ld_T0_A0[ot]();
1944
                opreg = OR_TMP0;
1945
            } else {
1946
                opreg = rm + OR_EAX;
1947
            }
1948

    
1949
            /* simpler op */
1950
            if (shift == 0) {
1951
                gen_shift(s, op, ot, opreg, OR_ECX);
1952
            } else {
1953
                if (shift == 2) {
1954
                    shift = ldub(s->pc++);
1955
                }
1956
                gen_shifti(s, op, ot, opreg, shift);
1957
            }
1958

    
1959
            if (mod != 3) {
1960
                gen_op_st_T0_A0[ot]();
1961
            }
1962
        }
1963
        break;
1964
    case 0xd0:
1965
    case 0xd1:
1966
        /* shift Ev,1 */
1967
        shift = 1;
1968
        goto grp2;
1969
    case 0xd2:
1970
    case 0xd3:
1971
        /* shift Ev,cl */
1972
        shift = 0;
1973
        goto grp2;
1974

    
1975
    case 0x1a4: /* shld imm */
1976
        op = 0;
1977
        shift = 1;
1978
        goto do_shiftd;
1979
    case 0x1a5: /* shld cl */
1980
        op = 0;
1981
        shift = 0;
1982
        goto do_shiftd;
1983
    case 0x1ac: /* shrd imm */
1984
        op = 1;
1985
        shift = 1;
1986
        goto do_shiftd;
1987
    case 0x1ad: /* shrd cl */
1988
        op = 1;
1989
        shift = 0;
1990
    do_shiftd:
1991
        ot = dflag ? OT_LONG : OT_WORD;
1992
        modrm = ldub(s->pc++);
1993
        mod = (modrm >> 6) & 3;
1994
        rm = modrm & 7;
1995
        reg = (modrm >> 3) & 7;
1996
        
1997
        if (mod != 3) {
1998
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1999
            gen_op_ld_T0_A0[ot]();
2000
        } else {
2001
            gen_op_mov_TN_reg[ot][0][rm]();
2002
        }
2003
        gen_op_mov_TN_reg[ot][1][reg]();
2004
        
2005
        if (shift) {
2006
            val = ldub(s->pc++);
2007
            val &= 0x1f;
2008
            if (val) {
2009
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2010
                if (op == 0 && ot != OT_WORD)
2011
                    s->cc_op = CC_OP_SHLB + ot;
2012
                else
2013
                    s->cc_op = CC_OP_SARB + ot;
2014
            }
2015
        } else {
2016
            if (s->cc_op != CC_OP_DYNAMIC)
2017
                gen_op_set_cc_op(s->cc_op);
2018
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2019
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2020
        }
2021
        if (mod != 3) {
2022
            gen_op_st_T0_A0[ot]();
2023
        } else {
2024
            gen_op_mov_reg_T0[ot][rm]();
2025
        }
2026
        break;
2027

    
2028
        /************************/
2029
        /* floats */
2030
    case 0xd8 ... 0xdf: 
2031
        modrm = ldub(s->pc++);
2032
        mod = (modrm >> 6) & 3;
2033
        rm = modrm & 7;
2034
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2035
        
2036
        if (mod != 3) {
2037
            /* memory op */
2038
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2039
            switch(op) {
2040
            case 0x00 ... 0x07: /* fxxxs */
2041
            case 0x10 ... 0x17: /* fixxxl */
2042
            case 0x20 ... 0x27: /* fxxxl */
2043
            case 0x30 ... 0x37: /* fixxx */
2044
                {
2045
                    int op1;
2046
                    op1 = op & 7;
2047

    
2048
                    switch(op >> 4) {
2049
                    case 0:
2050
                        gen_op_flds_FT0_A0();
2051
                        break;
2052
                    case 1:
2053
                        gen_op_fildl_FT0_A0();
2054
                        break;
2055
                    case 2:
2056
                        gen_op_fldl_FT0_A0();
2057
                        break;
2058
                    case 3:
2059
                    default:
2060
                        gen_op_fild_FT0_A0();
2061
                        break;
2062
                    }
2063
                    
2064
                    gen_op_fp_arith_ST0_FT0[op1]();
2065
                    if (op1 == 3) {
2066
                        /* fcomp needs pop */
2067
                        gen_op_fpop();
2068
                    }
2069
                }
2070
                break;
2071
            case 0x08: /* flds */
2072
            case 0x0a: /* fsts */
2073
            case 0x0b: /* fstps */
2074
            case 0x18: /* fildl */
2075
            case 0x1a: /* fistl */
2076
            case 0x1b: /* fistpl */
2077
            case 0x28: /* fldl */
2078
            case 0x2a: /* fstl */
2079
            case 0x2b: /* fstpl */
2080
            case 0x38: /* filds */
2081
            case 0x3a: /* fists */
2082
            case 0x3b: /* fistps */
2083
                
2084
                switch(op & 7) {
2085
                case 0:
2086
                    gen_op_fpush();
2087
                    switch(op >> 4) {
2088
                    case 0:
2089
                        gen_op_flds_ST0_A0();
2090
                        break;
2091
                    case 1:
2092
                        gen_op_fildl_ST0_A0();
2093
                        break;
2094
                    case 2:
2095
                        gen_op_fldl_ST0_A0();
2096
                        break;
2097
                    case 3:
2098
                    default:
2099
                        gen_op_fild_ST0_A0();
2100
                        break;
2101
                    }
2102
                    break;
2103
                default:
2104
                    switch(op >> 4) {
2105
                    case 0:
2106
                        gen_op_fsts_ST0_A0();
2107
                        break;
2108
                    case 1:
2109
                        gen_op_fistl_ST0_A0();
2110
                        break;
2111
                    case 2:
2112
                        gen_op_fstl_ST0_A0();
2113
                        break;
2114
                    case 3:
2115
                    default:
2116
                        gen_op_fist_ST0_A0();
2117
                        break;
2118
                    }
2119
                    if ((op & 7) == 3)
2120
                        gen_op_fpop();
2121
                    break;
2122
                }
2123
                break;
2124
            case 0x0d: /* fldcw mem */
2125
                gen_op_fldcw_A0();
2126
                break;
2127
            case 0x0f: /* fnstcw mem */
2128
                gen_op_fnstcw_A0();
2129
                break;
2130
            case 0x1d: /* fldt mem */
2131
                gen_op_fpush();
2132
                gen_op_fldt_ST0_A0();
2133
                break;
2134
            case 0x1f: /* fstpt mem */
2135
                gen_op_fstt_ST0_A0();
2136
                gen_op_fpop();
2137
                break;
2138
            case 0x2f: /* fnstsw mem */
2139
                gen_op_fnstsw_A0();
2140
                break;
2141
            case 0x3c: /* fbld */
2142
                gen_op_fpush();
2143
                gen_op_fbld_ST0_A0();
2144
                break;
2145
            case 0x3e: /* fbstp */
2146
                gen_op_fbst_ST0_A0();
2147
                gen_op_fpop();
2148
                break;
2149
            case 0x3d: /* fildll */
2150
                gen_op_fpush();
2151
                gen_op_fildll_ST0_A0();
2152
                break;
2153
            case 0x3f: /* fistpll */
2154
                gen_op_fistll_ST0_A0();
2155
                gen_op_fpop();
2156
                break;
2157
            default:
2158
                goto illegal_op;
2159
            }
2160
        } else {
2161
            /* register float ops */
2162
            opreg = rm;
2163

    
2164
            switch(op) {
2165
            case 0x08: /* fld sti */
2166
                gen_op_fpush();
2167
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2168
                break;
2169
            case 0x09: /* fxchg sti */
2170
                gen_op_fxchg_ST0_STN(opreg);
2171
                break;
2172
            case 0x0a: /* grp d9/2 */
2173
                switch(rm) {
2174
                case 0: /* fnop */
2175
                    break;
2176
                default:
2177
                    goto illegal_op;
2178
                }
2179
                break;
2180
            case 0x0c: /* grp d9/4 */
2181
                switch(rm) {
2182
                case 0: /* fchs */
2183
                    gen_op_fchs_ST0();
2184
                    break;
2185
                case 1: /* fabs */
2186
                    gen_op_fabs_ST0();
2187
                    break;
2188
                case 4: /* ftst */
2189
                    gen_op_fldz_FT0();
2190
                    gen_op_fcom_ST0_FT0();
2191
                    break;
2192
                case 5: /* fxam */
2193
                    gen_op_fxam_ST0();
2194
                    break;
2195
                default:
2196
                    goto illegal_op;
2197
                }
2198
                break;
2199
            case 0x0d: /* grp d9/5 */
2200
                {
2201
                    switch(rm) {
2202
                    case 0:
2203
                        gen_op_fpush();
2204
                        gen_op_fld1_ST0();
2205
                        break;
2206
                    case 1:
2207
                        gen_op_fpush();
2208
                        gen_op_fldl2t_ST0();
2209
                        break;
2210
                    case 2:
2211
                        gen_op_fpush();
2212
                        gen_op_fldl2e_ST0();
2213
                        break;
2214
                    case 3:
2215
                        gen_op_fpush();
2216
                        gen_op_fldpi_ST0();
2217
                        break;
2218
                    case 4:
2219
                        gen_op_fpush();
2220
                        gen_op_fldlg2_ST0();
2221
                        break;
2222
                    case 5:
2223
                        gen_op_fpush();
2224
                        gen_op_fldln2_ST0();
2225
                        break;
2226
                    case 6:
2227
                        gen_op_fpush();
2228
                        gen_op_fldz_ST0();
2229
                        break;
2230
                    default:
2231
                        goto illegal_op;
2232
                    }
2233
                }
2234
                break;
2235
            case 0x0e: /* grp d9/6 */
2236
                switch(rm) {
2237
                case 0: /* f2xm1 */
2238
                    gen_op_f2xm1();
2239
                    break;
2240
                case 1: /* fyl2x */
2241
                    gen_op_fyl2x();
2242
                    break;
2243
                case 2: /* fptan */
2244
                    gen_op_fptan();
2245
                    break;
2246
                case 3: /* fpatan */
2247
                    gen_op_fpatan();
2248
                    break;
2249
                case 4: /* fxtract */
2250
                    gen_op_fxtract();
2251
                    break;
2252
                case 5: /* fprem1 */
2253
                    gen_op_fprem1();
2254
                    break;
2255
                case 6: /* fdecstp */
2256
                    gen_op_fdecstp();
2257
                    break;
2258
                default:
2259
                case 7: /* fincstp */
2260
                    gen_op_fincstp();
2261
                    break;
2262
                }
2263
                break;
2264
            case 0x0f: /* grp d9/7 */
2265
                switch(rm) {
2266
                case 0: /* fprem */
2267
                    gen_op_fprem();
2268
                    break;
2269
                case 1: /* fyl2xp1 */
2270
                    gen_op_fyl2xp1();
2271
                    break;
2272
                case 2: /* fsqrt */
2273
                    gen_op_fsqrt();
2274
                    break;
2275
                case 3: /* fsincos */
2276
                    gen_op_fsincos();
2277
                    break;
2278
                case 5: /* fscale */
2279
                    gen_op_fscale();
2280
                    break;
2281
                case 4: /* frndint */
2282
                    gen_op_frndint();
2283
                    break;
2284
                case 6: /* fsin */
2285
                    gen_op_fsin();
2286
                    break;
2287
                default:
2288
                case 7: /* fcos */
2289
                    gen_op_fcos();
2290
                    break;
2291
                }
2292
                break;
2293
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2294
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2295
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2296
                {
2297
                    int op1;
2298
                    
2299
                    op1 = op & 7;
2300
                    if (op >= 0x20) {
2301
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2302
                        if (op >= 0x30)
2303
                            gen_op_fpop();
2304
                    } else {
2305
                        gen_op_fmov_FT0_STN(opreg);
2306
                        gen_op_fp_arith_ST0_FT0[op1]();
2307
                    }
2308
                }
2309
                break;
2310
            case 0x02: /* fcom */
2311
                gen_op_fmov_FT0_STN(opreg);
2312
                gen_op_fcom_ST0_FT0();
2313
                break;
2314
            case 0x03: /* fcomp */
2315
                gen_op_fmov_FT0_STN(opreg);
2316
                gen_op_fcom_ST0_FT0();
2317
                gen_op_fpop();
2318
                break;
2319
            case 0x15: /* da/5 */
2320
                switch(rm) {
2321
                case 1: /* fucompp */
2322
                    gen_op_fmov_FT0_STN(1);
2323
                    gen_op_fucom_ST0_FT0();
2324
                    gen_op_fpop();
2325
                    gen_op_fpop();
2326
                    break;
2327
                default:
2328
                    goto illegal_op;
2329
                }
2330
                break;
2331
            case 0x1c:
2332
                switch(rm) {
2333
                case 2: /* fclex */
2334
                    gen_op_fclex();
2335
                    break;
2336
                case 3: /* fninit */
2337
                    gen_op_fninit();
2338
                    break;
2339
                default:
2340
                    goto illegal_op;
2341
                }
2342
                break;
2343
            case 0x2a: /* fst sti */
2344
                gen_op_fmov_STN_ST0(opreg);
2345
                break;
2346
            case 0x2b: /* fstp sti */
2347
                gen_op_fmov_STN_ST0(opreg);
2348
                gen_op_fpop();
2349
                break;
2350
            case 0x2c: /* fucom st(i) */
2351
                gen_op_fmov_FT0_STN(opreg);
2352
                gen_op_fucom_ST0_FT0();
2353
                break;
2354
            case 0x2d: /* fucomp st(i) */
2355
                gen_op_fmov_FT0_STN(opreg);
2356
                gen_op_fucom_ST0_FT0();
2357
                gen_op_fpop();
2358
                break;
2359
            case 0x33: /* de/3 */
2360
                switch(rm) {
2361
                case 1: /* fcompp */
2362
                    gen_op_fmov_FT0_STN(1);
2363
                    gen_op_fcom_ST0_FT0();
2364
                    gen_op_fpop();
2365
                    gen_op_fpop();
2366
                    break;
2367
                default:
2368
                    goto illegal_op;
2369
                }
2370
                break;
2371
            case 0x3c: /* df/4 */
2372
                switch(rm) {
2373
                case 0:
2374
                    gen_op_fnstsw_EAX();
2375
                    break;
2376
                default:
2377
                    goto illegal_op;
2378
                }
2379
                break;
2380
            default:
2381
                goto illegal_op;
2382
            }
2383
        }
2384
        break;
2385
        /************************/
2386
        /* string ops */
2387
    case 0xa4: /* movsS */
2388
    case 0xa5:
2389
        if ((b & 1) == 0)
2390
            ot = OT_BYTE;
2391
        else
2392
            ot = dflag ? OT_LONG : OT_WORD;
2393
        if (prefixes & PREFIX_REPZ) {
2394
            gen_op_movs[3 + ot]();
2395
        } else {
2396
            gen_op_movs[ot]();
2397
        }
2398
        break;
2399
        
2400
    case 0xaa: /* stosS */
2401
    case 0xab:
2402
        if ((b & 1) == 0)
2403
            ot = OT_BYTE;
2404
        else
2405
            ot = dflag ? OT_LONG : OT_WORD;
2406
        if (prefixes & PREFIX_REPZ) {
2407
            gen_op_stos[3 + ot]();
2408
        } else {
2409
            gen_op_stos[ot]();
2410
        }
2411
        break;
2412
    case 0xac: /* lodsS */
2413
    case 0xad:
2414
        if ((b & 1) == 0)
2415
            ot = OT_BYTE;
2416
        else
2417
            ot = dflag ? OT_LONG : OT_WORD;
2418
        if (prefixes & PREFIX_REPZ) {
2419
            gen_op_lods[3 + ot]();
2420
        } else {
2421
            gen_op_lods[ot]();
2422
        }
2423
        break;
2424
    case 0xae: /* scasS */
2425
    case 0xaf:
2426
        if ((b & 1) == 0)
2427
            ot = OT_BYTE;
2428
        else
2429
            ot = dflag ? OT_LONG : OT_WORD;
2430
        if (prefixes & PREFIX_REPNZ) {
2431
            if (s->cc_op != CC_OP_DYNAMIC)
2432
                gen_op_set_cc_op(s->cc_op);
2433
            gen_op_scas[6 + ot]();
2434
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2435
        } else if (prefixes & PREFIX_REPZ) {
2436
            if (s->cc_op != CC_OP_DYNAMIC)
2437
                gen_op_set_cc_op(s->cc_op);
2438
            gen_op_scas[3 + ot]();
2439
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2440
        } else {
2441
            gen_op_scas[ot]();
2442
            s->cc_op = CC_OP_SUBB + ot;
2443
        }
2444
        break;
2445

    
2446
    case 0xa6: /* cmpsS */
2447
    case 0xa7:
2448
        if ((b & 1) == 0)
2449
            ot = OT_BYTE;
2450
        else
2451
            ot = dflag ? OT_LONG : OT_WORD;
2452
        if (prefixes & PREFIX_REPNZ) {
2453
            if (s->cc_op != CC_OP_DYNAMIC)
2454
                gen_op_set_cc_op(s->cc_op);
2455
            gen_op_cmps[6 + ot]();
2456
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2457
        } else if (prefixes & PREFIX_REPZ) {
2458
            if (s->cc_op != CC_OP_DYNAMIC)
2459
                gen_op_set_cc_op(s->cc_op);
2460
            gen_op_cmps[3 + ot]();
2461
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2462
        } else {
2463
            gen_op_cmps[ot]();
2464
            s->cc_op = CC_OP_SUBB + ot;
2465
        }
2466
        break;
2467
        
2468
        /************************/
2469
        /* port I/O */
2470
    case 0x6c: /* insS */
2471
    case 0x6d:
2472
        if ((b & 1) == 0)
2473
            ot = OT_BYTE;
2474
        else
2475
            ot = dflag ? OT_LONG : OT_WORD;
2476
        if (prefixes & PREFIX_REPZ) {
2477
            gen_op_ins[3 + ot]();
2478
        } else {
2479
            gen_op_ins[ot]();
2480
        }
2481
        break;
2482
    case 0x6e: /* outsS */
2483
    case 0x6f:
2484
        if ((b & 1) == 0)
2485
            ot = OT_BYTE;
2486
        else
2487
            ot = dflag ? OT_LONG : OT_WORD;
2488
        if (prefixes & PREFIX_REPZ) {
2489
            gen_op_outs[3 + ot]();
2490
        } else {
2491
            gen_op_outs[ot]();
2492
        }
2493
        break;
2494
    case 0xe4:
2495
    case 0xe5:
2496
        if ((b & 1) == 0)
2497
            ot = OT_BYTE;
2498
        else
2499
            ot = dflag ? OT_LONG : OT_WORD;
2500
        val = ldub(s->pc++);
2501
        gen_op_movl_T0_im(val);
2502
        gen_op_in[ot]();
2503
        gen_op_mov_reg_T1[ot][R_EAX]();
2504
        break;
2505
    case 0xe6:
2506
    case 0xe7:
2507
        if ((b & 1) == 0)
2508
            ot = OT_BYTE;
2509
        else
2510
            ot = dflag ? OT_LONG : OT_WORD;
2511
        val = ldub(s->pc++);
2512
        gen_op_movl_T0_im(val);
2513
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2514
        gen_op_out[ot]();
2515
        break;
2516
    case 0xec:
2517
    case 0xed:
2518
        if ((b & 1) == 0)
2519
            ot = OT_BYTE;
2520
        else
2521
            ot = dflag ? OT_LONG : OT_WORD;
2522
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2523
        gen_op_in[ot]();
2524
        gen_op_mov_reg_T1[ot][R_EAX]();
2525
        break;
2526
    case 0xee:
2527
    case 0xef:
2528
        if ((b & 1) == 0)
2529
            ot = OT_BYTE;
2530
        else
2531
            ot = dflag ? OT_LONG : OT_WORD;
2532
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2533
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2534
        gen_op_out[ot]();
2535
        break;
2536

    
2537
        /************************/
2538
        /* control */
2539
    case 0xc2: /* ret im */
2540
        /* XXX: handle stack pop ? */
2541
        val = ldsw(s->pc);
2542
        s->pc += 2;
2543
        gen_op_popl_T0();
2544
        gen_op_addl_ESP_im(val);
2545
        gen_op_jmp_T0();
2546
        s->is_jmp = 1;
2547
        break;
2548
    case 0xc3: /* ret */
2549
        gen_op_popl_T0();
2550
        gen_op_jmp_T0();
2551
        s->is_jmp = 1;
2552
        break;
2553
    case 0xe8: /* call */
2554
        val = insn_get(s, OT_LONG);
2555
        val += (long)s->pc;
2556
        gen_op_movl_T1_im((long)s->pc);
2557
        gen_op_pushl_T1();
2558
        gen_op_jmp_im(val);
2559
        s->is_jmp = 1;
2560
        break;
2561
    case 0xe9: /* jmp */
2562
        val = insn_get(s, OT_LONG);
2563
        val += (long)s->pc;
2564
        gen_op_jmp_im(val);
2565
        s->is_jmp = 1;
2566
        break;
2567
    case 0xeb: /* jmp Jb */
2568
        val = (int8_t)insn_get(s, OT_BYTE);
2569
        val += (long)s->pc;
2570
        gen_op_jmp_im(val);
2571
        s->is_jmp = 1;
2572
        break;
2573
    case 0x70 ... 0x7f: /* jcc Jb */
2574
        val = (int8_t)insn_get(s, OT_BYTE);
2575
        val += (long)s->pc;
2576
        goto do_jcc;
2577
    case 0x180 ... 0x18f: /* jcc Jv */
2578
        if (dflag) {
2579
            val = insn_get(s, OT_LONG);
2580
        } else {
2581
            val = (int16_t)insn_get(s, OT_WORD); 
2582
        }
2583
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2584
    do_jcc:
2585
        gen_jcc(s, b, val);
2586
        s->is_jmp = 1;
2587
        break;
2588

    
2589
    case 0x190 ... 0x19f:
2590
        modrm = ldub(s->pc++);
2591
        gen_setcc(s, b);
2592
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2593
        break;
2594

    
2595
        /************************/
2596
        /* flags */
2597
    case 0x9c: /* pushf */
2598
        if (s->cc_op != CC_OP_DYNAMIC)
2599
            gen_op_set_cc_op(s->cc_op);
2600
        gen_op_movl_T0_eflags();
2601
        gen_op_pushl_T0();
2602
        break;
2603
    case 0x9d: /* popf */
2604
        gen_op_popl_T0();
2605
        gen_op_movl_eflags_T0();
2606
        s->cc_op = CC_OP_EFLAGS;
2607
        break;
2608
    case 0x9e: /* sahf */
2609
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2610
        if (s->cc_op != CC_OP_DYNAMIC)
2611
            gen_op_set_cc_op(s->cc_op);
2612
        gen_op_movb_eflags_T0();
2613
        s->cc_op = CC_OP_EFLAGS;
2614
        break;
2615
    case 0x9f: /* lahf */
2616
        if (s->cc_op != CC_OP_DYNAMIC)
2617
            gen_op_set_cc_op(s->cc_op);
2618
        gen_op_movl_T0_eflags();
2619
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2620
        break;
2621
    case 0xf5: /* cmc */
2622
        if (s->cc_op != CC_OP_DYNAMIC)
2623
            gen_op_set_cc_op(s->cc_op);
2624
        gen_op_cmc();
2625
        s->cc_op = CC_OP_EFLAGS;
2626
        break;
2627
    case 0xf8: /* clc */
2628
        if (s->cc_op != CC_OP_DYNAMIC)
2629
            gen_op_set_cc_op(s->cc_op);
2630
        gen_op_clc();
2631
        s->cc_op = CC_OP_EFLAGS;
2632
        break;
2633
    case 0xf9: /* stc */
2634
        if (s->cc_op != CC_OP_DYNAMIC)
2635
            gen_op_set_cc_op(s->cc_op);
2636
        gen_op_stc();
2637
        s->cc_op = CC_OP_EFLAGS;
2638
        break;
2639
    case 0xfc: /* cld */
2640
        gen_op_cld();
2641
        break;
2642
    case 0xfd: /* std */
2643
        gen_op_std();
2644
        break;
2645

    
2646
        /************************/
2647
        /* bit operations */
2648
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
2649
        ot = dflag ? OT_LONG : OT_WORD;
2650
        modrm = ldub(s->pc++);
2651
        op = (modrm >> 3) & 7;
2652
        mod = (modrm >> 6) & 3;
2653
        rm = modrm & 7;
2654
        if (mod != 3) {
2655
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2656
            gen_op_ld_T0_A0[ot]();
2657
        } else {
2658
            gen_op_mov_TN_reg[ot][0][rm]();
2659
        }
2660
        /* load shift */
2661
        val = ldub(s->pc++);
2662
        gen_op_movl_T1_im(val);
2663
        if (op < 4)
2664
            goto illegal_op;
2665
        op -= 4;
2666
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2667
        s->cc_op = CC_OP_SARB + ot;
2668
        if (op != 0) {
2669
            if (mod != 3)
2670
                gen_op_st_T0_A0[ot]();
2671
            else
2672
                gen_op_mov_reg_T0[ot][rm]();
2673
        }
2674
        break;
2675
    case 0x1a3: /* bt Gv, Ev */
2676
        op = 0;
2677
        goto do_btx;
2678
    case 0x1ab: /* bts */
2679
        op = 1;
2680
        goto do_btx;
2681
    case 0x1b3: /* btr */
2682
        op = 2;
2683
        goto do_btx;
2684
    case 0x1bb: /* btc */
2685
        op = 3;
2686
    do_btx:
2687
        ot = dflag ? OT_LONG : OT_WORD;
2688
        modrm = ldub(s->pc++);
2689
        reg = (modrm >> 3) & 7;
2690
        mod = (modrm >> 6) & 3;
2691
        rm = modrm & 7;
2692
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
2693
        if (mod != 3) {
2694
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2695
            /* specific case: we need to add a displacement */
2696
            if (ot == OT_WORD)
2697
                gen_op_add_bitw_A0_T1();
2698
            else
2699
                gen_op_add_bitl_A0_T1();
2700
            gen_op_ld_T0_A0[ot]();
2701
        } else {
2702
            gen_op_mov_TN_reg[ot][0][rm]();
2703
        }
2704
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2705
        s->cc_op = CC_OP_SARB + ot;
2706
        if (op != 0) {
2707
            if (mod != 3)
2708
                gen_op_st_T0_A0[ot]();
2709
            else
2710
                gen_op_mov_reg_T0[ot][rm]();
2711
        }
2712
        break;
2713
    case 0x1bc: /* bsf */
2714
    case 0x1bd: /* bsr */
2715
        ot = dflag ? OT_LONG : OT_WORD;
2716
        modrm = ldub(s->pc++);
2717
        reg = (modrm >> 3) & 7;
2718
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2719
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2720
        /* NOTE: we always write back the result. Intel doc says it is
2721
           undefined if T0 == 0 */
2722
        gen_op_mov_reg_T0[ot][reg]();
2723
        s->cc_op = CC_OP_LOGICB + ot;
2724
        break;
2725
        /************************/
2726
        /* bcd */
2727
    case 0x27: /* daa */
2728
        if (s->cc_op != CC_OP_DYNAMIC)
2729
            gen_op_set_cc_op(s->cc_op);
2730
        gen_op_daa();
2731
        s->cc_op = CC_OP_EFLAGS;
2732
        break;
2733
    case 0x2f: /* das */
2734
        if (s->cc_op != CC_OP_DYNAMIC)
2735
            gen_op_set_cc_op(s->cc_op);
2736
        gen_op_das();
2737
        s->cc_op = CC_OP_EFLAGS;
2738
        break;
2739
    case 0x37: /* aaa */
2740
        if (s->cc_op != CC_OP_DYNAMIC)
2741
            gen_op_set_cc_op(s->cc_op);
2742
        gen_op_aaa();
2743
        s->cc_op = CC_OP_EFLAGS;
2744
        break;
2745
    case 0x3f: /* aas */
2746
        if (s->cc_op != CC_OP_DYNAMIC)
2747
            gen_op_set_cc_op(s->cc_op);
2748
        gen_op_aas();
2749
        s->cc_op = CC_OP_EFLAGS;
2750
        break;
2751
    case 0xd4: /* aam */
2752
        val = ldub(s->pc++);
2753
        gen_op_aam(val);
2754
        s->cc_op = CC_OP_LOGICB;
2755
        break;
2756
    case 0xd5: /* aad */
2757
        val = ldub(s->pc++);
2758
        gen_op_aad(val);
2759
        s->cc_op = CC_OP_LOGICB;
2760
        break;
2761
        /************************/
2762
        /* misc */
2763
    case 0x90: /* nop */
2764
        break;
2765
    case 0xcc: /* int3 */
2766
        gen_op_int3((long)pc_start);
2767
        s->is_jmp = 1;
2768
        break;
2769
    case 0xcd: /* int N */
2770
        val = ldub(s->pc++);
2771
        /* XXX: currently we ignore the interrupt number */
2772
        gen_op_int_im((long)pc_start);
2773
        s->is_jmp = 1;
2774
        break;
2775
    case 0xce: /* into */
2776
        if (s->cc_op != CC_OP_DYNAMIC)
2777
            gen_op_set_cc_op(s->cc_op);
2778
        gen_op_into((long)pc_start, (long)s->pc);
2779
        s->is_jmp = 1;
2780
        break;
2781
    case 0x1c8 ... 0x1cf: /* bswap reg */
2782
        reg = b & 7;
2783
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
2784
        gen_op_bswapl_T0();
2785
        gen_op_mov_reg_T0[OT_LONG][reg]();
2786
        break;
2787
    case 0xd6: /* salc */
2788
        if (s->cc_op != CC_OP_DYNAMIC)
2789
            gen_op_set_cc_op(s->cc_op);
2790
        gen_op_salc();
2791
        break;
2792
    case 0xe0: /* loopnz */
2793
    case 0xe1: /* loopz */
2794
        if (s->cc_op != CC_OP_DYNAMIC)
2795
            gen_op_set_cc_op(s->cc_op);
2796
        /* FALL THRU */
2797
    case 0xe2: /* loop */
2798
    case 0xe3: /* jecxz */
2799
        val = (int8_t)insn_get(s, OT_BYTE);
2800
        val += (long)s->pc;
2801
        gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
2802
        s->is_jmp = 1;
2803
        break;
2804
    case 0x1a2: /* rdtsc */
2805
        gen_op_rdtsc();
2806
        break;
2807
#if 0
2808
    case 0x1a2: /* cpuid */
2809
        gen_insn0(OP_ASM);
2810
        break;
2811
#endif
2812
    default:
2813
        goto illegal_op;
2814
    }
2815
    return (long)s->pc;
2816
 illegal_op:
2817
    return -1;
2818
}
2819

    
2820
/* return the next pc */
2821
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
2822
                     int *gen_code_size_ptr, uint8_t *pc_start, 
2823
                     int flags)
2824
{
2825
    DisasContext dc1, *dc = &dc1;
2826
    uint8_t *gen_code_end, *pc_ptr;
2827
    long ret;
2828
#ifdef DEBUG_DISAS
2829
    struct disassemble_info disasm_info;
2830
#endif
2831
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
2832
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
2833
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
2834
    dc->cc_op = CC_OP_DYNAMIC;
2835
    gen_code_ptr = gen_code_buf;
2836
    gen_code_end = gen_code_buf + max_code_size - 4096;
2837
    gen_start();
2838

    
2839
    dc->is_jmp = 0;
2840
    pc_ptr = pc_start;
2841
    do {
2842
        ret = disas_insn(dc, pc_ptr);
2843
        if (ret == -1) {
2844
            error("unknown instruction at PC=0x%x B=%02x %02x %02x", 
2845
                  pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
2846
            abort();
2847
        }
2848
        pc_ptr = (void *)ret;
2849
    } while (!dc->is_jmp && gen_code_ptr < gen_code_end);
2850
    /* we must store the eflags state if it is not already done */
2851
    if (dc->cc_op != CC_OP_DYNAMIC)
2852
        gen_op_set_cc_op(dc->cc_op);
2853
    if (dc->is_jmp != 1) {
2854
        /* we add an additionnal jmp to update the simulated PC */
2855
        gen_op_jmp_im(ret);
2856
    }
2857
    gen_end();
2858
    *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2859

    
2860
#ifdef DEBUG_DISAS
2861
    if (loglevel) {
2862
        uint8_t *pc;
2863
        int count;
2864

    
2865
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2866
#if 0        
2867
        disasm_info.flavour = bfd_get_flavour (abfd);
2868
        disasm_info.arch = bfd_get_arch (abfd);
2869
        disasm_info.mach = bfd_get_mach (abfd);
2870
#endif
2871
#ifdef WORDS_BIGENDIAN
2872
        disasm_info.endian = BFD_ENDIAN_BIG;
2873
#else
2874
        disasm_info.endian = BFD_ENDIAN_LITTLE;
2875
#endif        
2876
        fprintf(logfile, "IN:\n");
2877
        disasm_info.buffer = pc_start;
2878
        disasm_info.buffer_vma = (unsigned long)pc_start;
2879
        disasm_info.buffer_length = pc_ptr - pc_start;
2880
        pc = pc_start;
2881
        while (pc < pc_ptr) {
2882
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2883
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2884
            fprintf(logfile, "\n");
2885
            pc += count;
2886
        }
2887
        fprintf(logfile, "\n");
2888
        
2889
        pc = gen_code_buf;
2890
        disasm_info.buffer = pc;
2891
        disasm_info.buffer_vma = (unsigned long)pc;
2892
        disasm_info.buffer_length = *gen_code_size_ptr;
2893
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2894
        while (pc < gen_code_ptr) {
2895
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2896
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2897
            fprintf(logfile, "\n");
2898
            pc += count;
2899
        }
2900
        fprintf(logfile, "\n");
2901
    }
2902
#endif
2903
    return 0;
2904
}
2905

    
2906
CPUX86State *cpu_x86_init(void)
2907
{
2908
    CPUX86State *env;
2909
    int i;
2910

    
2911
    cpu_x86_tblocks_init();
2912

    
2913
    env = malloc(sizeof(CPUX86State));
2914
    if (!env)
2915
        return NULL;
2916
    memset(env, 0, sizeof(CPUX86State));
2917
    /* basic FPU init */
2918
    for(i = 0;i < 8; i++)
2919
        env->fptags[i] = 1;
2920
    env->fpuc = 0x37f;
2921
    /* flags setup */
2922
    env->cc_op = CC_OP_EFLAGS;
2923
    env->df = 1;
2924
    return env;
2925
}
2926

    
2927
void cpu_x86_close(CPUX86State *env)
2928
{
2929
    free(env);
2930
}