Statistics
| Branch: | Revision:

root / translate-i386.c @ 982b4315

History | View | Annotate | Download (102.4 kB)

1
/*
2
 *  i386 translation
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library 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 GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <signal.h>
26
#include <assert.h>
27

    
28
#include "disas.h"
29

    
30
#define DEBUG_DISAS
31

    
32
#define IN_OP_I386
33
#include "cpu-i386.h"
34

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

    
39
/* XXX: move that elsewhere */
40
static uint16_t *gen_opc_ptr;
41
static uint32_t *gen_opparam_ptr;
42
int __op_param1, __op_param2, __op_param3;
43

    
44
#ifdef __i386__
45
static inline void flush_icache_range(unsigned long start, unsigned long stop)
46
{
47
}
48
#endif
49

    
50
#ifdef __s390__
51
static inline void flush_icache_range(unsigned long start, unsigned long stop)
52
{
53
}
54
#endif
55

    
56
#ifdef __ia64__
57
static inline void flush_icache_range(unsigned long start, unsigned long stop)
58
{
59
}
60
#endif
61

    
62
#ifdef __powerpc__
63

    
64
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
65

    
66
static void inline flush_icache_range(unsigned long start, unsigned long stop)
67
{
68
    unsigned long p;
69

    
70
    p = start & ~(MIN_CACHE_LINE_SIZE - 1);
71
    stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
72
    
73
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
74
        asm ("dcbst 0,%0;" : : "r"(p) : "memory");
75
    }
76
    asm ("sync");
77
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
78
        asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
79
    }
80
    asm ("sync");
81
    asm ("isync");
82
}
83
#endif
84

    
85
#ifdef __alpha__
86
static inline void flush_icache_range(unsigned long start, unsigned long stop)
87
{
88
    asm ("imb");
89
}
90
#endif
91

    
92
#ifdef __sparc__
93

    
94
static void inline flush_icache_range(unsigned long start, unsigned long stop)
95
{
96
        unsigned long p;
97

    
98
        p = start & ~(8UL - 1UL);
99
        stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
100

    
101
        for (; p < stop; p += 8)
102
                __asm__ __volatile__("flush\t%0" : : "r" (p));
103
}
104

    
105
#endif
106

    
107
extern FILE *logfile;
108
extern int loglevel;
109

    
110
#define PREFIX_REPZ   0x01
111
#define PREFIX_REPNZ  0x02
112
#define PREFIX_LOCK   0x04
113
#define PREFIX_DATA   0x08
114
#define PREFIX_ADR    0x10
115
#define PREFIX_FWAIT  0x20
116

    
117
typedef struct DisasContext {
118
    /* current insn context */
119
    int override; /* -1 if no override */
120
    int prefix;
121
    int aflag, dflag;
122
    uint8_t *pc; /* pc = eip + cs_base */
123
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
124
                   static state change (stop translation) */
125
    /* current block context */
126
    uint8_t *cs_base; /* base of CS segment */
127
    int code32; /* 32 bit code segment */
128
    int ss32;   /* 32 bit stack segment */
129
    int cc_op;  /* current CC operation */
130
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
131
    int f_st;   /* currently unused */
132
    int vm86;   /* vm86 mode */
133
    int cpl;
134
    int iopl;
135
} DisasContext;
136

    
137
/* i386 arith/logic operations */
138
enum {
139
    OP_ADDL, 
140
    OP_ORL, 
141
    OP_ADCL, 
142
    OP_SBBL,
143
    OP_ANDL, 
144
    OP_SUBL, 
145
    OP_XORL, 
146
    OP_CMPL,
147
};
148

    
149
/* i386 shift ops */
150
enum {
151
    OP_ROL, 
152
    OP_ROR, 
153
    OP_RCL, 
154
    OP_RCR, 
155
    OP_SHL, 
156
    OP_SHR, 
157
    OP_SHL1, /* undocumented */
158
    OP_SAR = 7,
159
};
160

    
161
enum {
162
#define DEF(s, n) INDEX_op_ ## s,
163
#include "opc-i386.h"
164
#undef DEF
165
    NB_OPS,
166
};
167

    
168
#include "op-i386.h"
169

    
170
/* operand size */
171
enum {
172
    OT_BYTE = 0,
173
    OT_WORD,
174
    OT_LONG, 
175
    OT_QUAD,
176
};
177

    
178
enum {
179
    /* I386 int registers */
180
    OR_EAX,   /* MUST be even numbered */
181
    OR_ECX,
182
    OR_EDX,
183
    OR_EBX,
184
    OR_ESP,
185
    OR_EBP,
186
    OR_ESI,
187
    OR_EDI,
188
    OR_TMP0,    /* temporary operand register */
189
    OR_TMP1,
190
    OR_A0, /* temporary register used when doing address evaluation */
191
    OR_ZERO, /* fixed zero register */
192
    NB_OREGS,
193
};
194

    
195
typedef void (GenOpFunc)(void);
196
typedef void (GenOpFunc1)(long);
197
typedef void (GenOpFunc2)(long, long);
198
                    
199
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
200
    [OT_BYTE] = {
201
        gen_op_movb_EAX_T0,
202
        gen_op_movb_ECX_T0,
203
        gen_op_movb_EDX_T0,
204
        gen_op_movb_EBX_T0,
205
        gen_op_movh_EAX_T0,
206
        gen_op_movh_ECX_T0,
207
        gen_op_movh_EDX_T0,
208
        gen_op_movh_EBX_T0,
209
    },
210
    [OT_WORD] = {
211
        gen_op_movw_EAX_T0,
212
        gen_op_movw_ECX_T0,
213
        gen_op_movw_EDX_T0,
214
        gen_op_movw_EBX_T0,
215
        gen_op_movw_ESP_T0,
216
        gen_op_movw_EBP_T0,
217
        gen_op_movw_ESI_T0,
218
        gen_op_movw_EDI_T0,
219
    },
220
    [OT_LONG] = {
221
        gen_op_movl_EAX_T0,
222
        gen_op_movl_ECX_T0,
223
        gen_op_movl_EDX_T0,
224
        gen_op_movl_EBX_T0,
225
        gen_op_movl_ESP_T0,
226
        gen_op_movl_EBP_T0,
227
        gen_op_movl_ESI_T0,
228
        gen_op_movl_EDI_T0,
229
    },
230
};
231

    
232
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
233
    [OT_BYTE] = {
234
        gen_op_movb_EAX_T1,
235
        gen_op_movb_ECX_T1,
236
        gen_op_movb_EDX_T1,
237
        gen_op_movb_EBX_T1,
238
        gen_op_movh_EAX_T1,
239
        gen_op_movh_ECX_T1,
240
        gen_op_movh_EDX_T1,
241
        gen_op_movh_EBX_T1,
242
    },
243
    [OT_WORD] = {
244
        gen_op_movw_EAX_T1,
245
        gen_op_movw_ECX_T1,
246
        gen_op_movw_EDX_T1,
247
        gen_op_movw_EBX_T1,
248
        gen_op_movw_ESP_T1,
249
        gen_op_movw_EBP_T1,
250
        gen_op_movw_ESI_T1,
251
        gen_op_movw_EDI_T1,
252
    },
253
    [OT_LONG] = {
254
        gen_op_movl_EAX_T1,
255
        gen_op_movl_ECX_T1,
256
        gen_op_movl_EDX_T1,
257
        gen_op_movl_EBX_T1,
258
        gen_op_movl_ESP_T1,
259
        gen_op_movl_EBP_T1,
260
        gen_op_movl_ESI_T1,
261
        gen_op_movl_EDI_T1,
262
    },
263
};
264

    
265
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
266
    [0] = {
267
        gen_op_movw_EAX_A0,
268
        gen_op_movw_ECX_A0,
269
        gen_op_movw_EDX_A0,
270
        gen_op_movw_EBX_A0,
271
        gen_op_movw_ESP_A0,
272
        gen_op_movw_EBP_A0,
273
        gen_op_movw_ESI_A0,
274
        gen_op_movw_EDI_A0,
275
    },
276
    [1] = {
277
        gen_op_movl_EAX_A0,
278
        gen_op_movl_ECX_A0,
279
        gen_op_movl_EDX_A0,
280
        gen_op_movl_EBX_A0,
281
        gen_op_movl_ESP_A0,
282
        gen_op_movl_EBP_A0,
283
        gen_op_movl_ESI_A0,
284
        gen_op_movl_EDI_A0,
285
    },
286
};
287

    
288
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
289
{
290
    [OT_BYTE] = {
291
        {
292
            gen_op_movl_T0_EAX,
293
            gen_op_movl_T0_ECX,
294
            gen_op_movl_T0_EDX,
295
            gen_op_movl_T0_EBX,
296
            gen_op_movh_T0_EAX,
297
            gen_op_movh_T0_ECX,
298
            gen_op_movh_T0_EDX,
299
            gen_op_movh_T0_EBX,
300
        },
301
        {
302
            gen_op_movl_T1_EAX,
303
            gen_op_movl_T1_ECX,
304
            gen_op_movl_T1_EDX,
305
            gen_op_movl_T1_EBX,
306
            gen_op_movh_T1_EAX,
307
            gen_op_movh_T1_ECX,
308
            gen_op_movh_T1_EDX,
309
            gen_op_movh_T1_EBX,
310
        },
311
    },
312
    [OT_WORD] = {
313
        {
314
            gen_op_movl_T0_EAX,
315
            gen_op_movl_T0_ECX,
316
            gen_op_movl_T0_EDX,
317
            gen_op_movl_T0_EBX,
318
            gen_op_movl_T0_ESP,
319
            gen_op_movl_T0_EBP,
320
            gen_op_movl_T0_ESI,
321
            gen_op_movl_T0_EDI,
322
        },
323
        {
324
            gen_op_movl_T1_EAX,
325
            gen_op_movl_T1_ECX,
326
            gen_op_movl_T1_EDX,
327
            gen_op_movl_T1_EBX,
328
            gen_op_movl_T1_ESP,
329
            gen_op_movl_T1_EBP,
330
            gen_op_movl_T1_ESI,
331
            gen_op_movl_T1_EDI,
332
        },
333
    },
334
    [OT_LONG] = {
335
        {
336
            gen_op_movl_T0_EAX,
337
            gen_op_movl_T0_ECX,
338
            gen_op_movl_T0_EDX,
339
            gen_op_movl_T0_EBX,
340
            gen_op_movl_T0_ESP,
341
            gen_op_movl_T0_EBP,
342
            gen_op_movl_T0_ESI,
343
            gen_op_movl_T0_EDI,
344
        },
345
        {
346
            gen_op_movl_T1_EAX,
347
            gen_op_movl_T1_ECX,
348
            gen_op_movl_T1_EDX,
349
            gen_op_movl_T1_EBX,
350
            gen_op_movl_T1_ESP,
351
            gen_op_movl_T1_EBP,
352
            gen_op_movl_T1_ESI,
353
            gen_op_movl_T1_EDI,
354
        },
355
    },
356
};
357

    
358
static GenOpFunc *gen_op_movl_A0_reg[8] = {
359
    gen_op_movl_A0_EAX,
360
    gen_op_movl_A0_ECX,
361
    gen_op_movl_A0_EDX,
362
    gen_op_movl_A0_EBX,
363
    gen_op_movl_A0_ESP,
364
    gen_op_movl_A0_EBP,
365
    gen_op_movl_A0_ESI,
366
    gen_op_movl_A0_EDI,
367
};
368

    
369
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
370
    [0] = {
371
        gen_op_addl_A0_EAX,
372
        gen_op_addl_A0_ECX,
373
        gen_op_addl_A0_EDX,
374
        gen_op_addl_A0_EBX,
375
        gen_op_addl_A0_ESP,
376
        gen_op_addl_A0_EBP,
377
        gen_op_addl_A0_ESI,
378
        gen_op_addl_A0_EDI,
379
    },
380
    [1] = {
381
        gen_op_addl_A0_EAX_s1,
382
        gen_op_addl_A0_ECX_s1,
383
        gen_op_addl_A0_EDX_s1,
384
        gen_op_addl_A0_EBX_s1,
385
        gen_op_addl_A0_ESP_s1,
386
        gen_op_addl_A0_EBP_s1,
387
        gen_op_addl_A0_ESI_s1,
388
        gen_op_addl_A0_EDI_s1,
389
    },
390
    [2] = {
391
        gen_op_addl_A0_EAX_s2,
392
        gen_op_addl_A0_ECX_s2,
393
        gen_op_addl_A0_EDX_s2,
394
        gen_op_addl_A0_EBX_s2,
395
        gen_op_addl_A0_ESP_s2,
396
        gen_op_addl_A0_EBP_s2,
397
        gen_op_addl_A0_ESI_s2,
398
        gen_op_addl_A0_EDI_s2,
399
    },
400
    [3] = {
401
        gen_op_addl_A0_EAX_s3,
402
        gen_op_addl_A0_ECX_s3,
403
        gen_op_addl_A0_EDX_s3,
404
        gen_op_addl_A0_EBX_s3,
405
        gen_op_addl_A0_ESP_s3,
406
        gen_op_addl_A0_EBP_s3,
407
        gen_op_addl_A0_ESI_s3,
408
        gen_op_addl_A0_EDI_s3,
409
    },
410
};
411

    
412
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
413
    [0] = {
414
        gen_op_cmovw_EAX_T1_T0,
415
        gen_op_cmovw_ECX_T1_T0,
416
        gen_op_cmovw_EDX_T1_T0,
417
        gen_op_cmovw_EBX_T1_T0,
418
        gen_op_cmovw_ESP_T1_T0,
419
        gen_op_cmovw_EBP_T1_T0,
420
        gen_op_cmovw_ESI_T1_T0,
421
        gen_op_cmovw_EDI_T1_T0,
422
    },
423
    [1] = {
424
        gen_op_cmovl_EAX_T1_T0,
425
        gen_op_cmovl_ECX_T1_T0,
426
        gen_op_cmovl_EDX_T1_T0,
427
        gen_op_cmovl_EBX_T1_T0,
428
        gen_op_cmovl_ESP_T1_T0,
429
        gen_op_cmovl_EBP_T1_T0,
430
        gen_op_cmovl_ESI_T1_T0,
431
        gen_op_cmovl_EDI_T1_T0,
432
    },
433
};
434

    
435
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
436
    gen_op_addl_T0_T1_cc,
437
    gen_op_orl_T0_T1_cc,
438
    NULL,
439
    NULL,
440
    gen_op_andl_T0_T1_cc,
441
    gen_op_subl_T0_T1_cc,
442
    gen_op_xorl_T0_T1_cc,
443
    gen_op_cmpl_T0_T1_cc,
444
};
445

    
446
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
447
    [OT_BYTE] = {
448
        gen_op_adcb_T0_T1_cc,
449
        gen_op_sbbb_T0_T1_cc,
450
    },
451
    [OT_WORD] = {
452
        gen_op_adcw_T0_T1_cc,
453
        gen_op_sbbw_T0_T1_cc,
454
    },
455
    [OT_LONG] = {
456
        gen_op_adcl_T0_T1_cc,
457
        gen_op_sbbl_T0_T1_cc,
458
    },
459
};
460

    
461
static const int cc_op_arithb[8] = {
462
    CC_OP_ADDB,
463
    CC_OP_LOGICB,
464
    CC_OP_ADDB,
465
    CC_OP_SUBB,
466
    CC_OP_LOGICB,
467
    CC_OP_SUBB,
468
    CC_OP_LOGICB,
469
    CC_OP_SUBB,
470
};
471

    
472
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
473
    gen_op_cmpxchgb_T0_T1_EAX_cc,
474
    gen_op_cmpxchgw_T0_T1_EAX_cc,
475
    gen_op_cmpxchgl_T0_T1_EAX_cc,
476
};
477

    
478
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
479
    [OT_BYTE] = {
480
        gen_op_rolb_T0_T1_cc,
481
        gen_op_rorb_T0_T1_cc,
482
        gen_op_rclb_T0_T1_cc,
483
        gen_op_rcrb_T0_T1_cc,
484
        gen_op_shlb_T0_T1_cc,
485
        gen_op_shrb_T0_T1_cc,
486
        gen_op_shlb_T0_T1_cc,
487
        gen_op_sarb_T0_T1_cc,
488
    },
489
    [OT_WORD] = {
490
        gen_op_rolw_T0_T1_cc,
491
        gen_op_rorw_T0_T1_cc,
492
        gen_op_rclw_T0_T1_cc,
493
        gen_op_rcrw_T0_T1_cc,
494
        gen_op_shlw_T0_T1_cc,
495
        gen_op_shrw_T0_T1_cc,
496
        gen_op_shlw_T0_T1_cc,
497
        gen_op_sarw_T0_T1_cc,
498
    },
499
    [OT_LONG] = {
500
        gen_op_roll_T0_T1_cc,
501
        gen_op_rorl_T0_T1_cc,
502
        gen_op_rcll_T0_T1_cc,
503
        gen_op_rcrl_T0_T1_cc,
504
        gen_op_shll_T0_T1_cc,
505
        gen_op_shrl_T0_T1_cc,
506
        gen_op_shll_T0_T1_cc,
507
        gen_op_sarl_T0_T1_cc,
508
    },
509
};
510

    
511
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
512
    [0] = {
513
        gen_op_shldw_T0_T1_im_cc,
514
        gen_op_shrdw_T0_T1_im_cc,
515
    },
516
    [1] = {
517
        gen_op_shldl_T0_T1_im_cc,
518
        gen_op_shrdl_T0_T1_im_cc,
519
    },
520
};
521

    
522
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
523
    [0] = {
524
        gen_op_shldw_T0_T1_ECX_cc,
525
        gen_op_shrdw_T0_T1_ECX_cc,
526
    },
527
    [1] = {
528
        gen_op_shldl_T0_T1_ECX_cc,
529
        gen_op_shrdl_T0_T1_ECX_cc,
530
    },
531
};
532

    
533
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
534
    [0] = {
535
        gen_op_btw_T0_T1_cc,
536
        gen_op_btsw_T0_T1_cc,
537
        gen_op_btrw_T0_T1_cc,
538
        gen_op_btcw_T0_T1_cc,
539
    },
540
    [1] = {
541
        gen_op_btl_T0_T1_cc,
542
        gen_op_btsl_T0_T1_cc,
543
        gen_op_btrl_T0_T1_cc,
544
        gen_op_btcl_T0_T1_cc,
545
    },
546
};
547

    
548
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
549
    [0] = {
550
        gen_op_bsfw_T0_cc,
551
        gen_op_bsrw_T0_cc,
552
    },
553
    [1] = {
554
        gen_op_bsfl_T0_cc,
555
        gen_op_bsrl_T0_cc,
556
    },
557
};
558

    
559
static GenOpFunc *gen_op_lds_T0_A0[3] = {
560
    gen_op_ldsb_T0_A0,
561
    gen_op_ldsw_T0_A0,
562
};
563

    
564
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
565
    gen_op_ldub_T0_A0,
566
    gen_op_lduw_T0_A0,
567
};
568

    
569
/* sign does not matter */
570
static GenOpFunc *gen_op_ld_T0_A0[3] = {
571
    gen_op_ldub_T0_A0,
572
    gen_op_lduw_T0_A0,
573
    gen_op_ldl_T0_A0,
574
};
575

    
576
static GenOpFunc *gen_op_ld_T1_A0[3] = {
577
    gen_op_ldub_T1_A0,
578
    gen_op_lduw_T1_A0,
579
    gen_op_ldl_T1_A0,
580
};
581

    
582
static GenOpFunc *gen_op_st_T0_A0[3] = {
583
    gen_op_stb_T0_A0,
584
    gen_op_stw_T0_A0,
585
    gen_op_stl_T0_A0,
586
};
587

    
588
/* the _a32 and _a16 string operations use A0 as the base register. */
589

    
590
#define STRINGOP(x) \
591
    gen_op_ ## x ## b_fast, \
592
    gen_op_ ## x ## w_fast, \
593
    gen_op_ ## x ## l_fast, \
594
    gen_op_ ## x ## b_a32, \
595
    gen_op_ ## x ## w_a32, \
596
    gen_op_ ## x ## l_a32, \
597
    gen_op_ ## x ## b_a16, \
598
    gen_op_ ## x ## w_a16, \
599
    gen_op_ ## x ## l_a16,
600
     
601
static GenOpFunc *gen_op_movs[9 * 2] = {
602
    STRINGOP(movs)
603
    STRINGOP(rep_movs)
604
};
605

    
606
static GenOpFunc *gen_op_stos[9 * 2] = {
607
    STRINGOP(stos)
608
    STRINGOP(rep_stos)
609
};
610

    
611
static GenOpFunc *gen_op_lods[9 * 2] = {
612
    STRINGOP(lods)
613
    STRINGOP(rep_lods)
614
};
615

    
616
static GenOpFunc *gen_op_scas[9 * 3] = {
617
    STRINGOP(scas)
618
    STRINGOP(repz_scas)
619
    STRINGOP(repnz_scas)
620
};
621

    
622
static GenOpFunc *gen_op_cmps[9 * 3] = {
623
    STRINGOP(cmps)
624
    STRINGOP(repz_cmps)
625
    STRINGOP(repnz_cmps)
626
};
627

    
628
static GenOpFunc *gen_op_ins[9 * 2] = {
629
    STRINGOP(ins)
630
    STRINGOP(rep_ins)
631
};
632

    
633

    
634
static GenOpFunc *gen_op_outs[9 * 2] = {
635
    STRINGOP(outs)
636
    STRINGOP(rep_outs)
637
};
638

    
639

    
640
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
641
{
642
    int index, override;
643

    
644
    override = s->override;
645
    if (s->aflag) {
646
        /* 32 bit address */
647
        if (s->addseg && override < 0)
648
            override = R_DS;
649
        if (override >= 0) {
650
            gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
651
            index = 3 + ot;
652
        } else {
653
            index = ot;
654
        }
655
    } else {
656
        if (override < 0)
657
            override = R_DS;
658
        gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
659
        /* 16 address, always override */
660
        index = 6 + ot;
661
    }
662
    func[index]();
663
}
664

    
665
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
666
{
667
    int index;
668
            
669
    if (s->aflag) {
670
        if (s->addseg) {
671
            index = 3 + ot;
672
        } else {
673
            index = ot;
674
        }
675
    } else {
676
        index = 6 + ot;
677
    }
678
    func[index]();
679
}
680

    
681

    
682
static GenOpFunc *gen_op_in[3] = {
683
    gen_op_inb_T0_T1,
684
    gen_op_inw_T0_T1,
685
    gen_op_inl_T0_T1,
686
};
687

    
688
static GenOpFunc *gen_op_out[3] = {
689
    gen_op_outb_T0_T1,
690
    gen_op_outw_T0_T1,
691
    gen_op_outl_T0_T1,
692
};
693

    
694
enum {
695
    JCC_O,
696
    JCC_B,
697
    JCC_Z,
698
    JCC_BE,
699
    JCC_S,
700
    JCC_P,
701
    JCC_L,
702
    JCC_LE,
703
};
704

    
705
static GenOpFunc2 *gen_jcc_slow[8] = {
706
    gen_op_jo_cc,
707
    gen_op_jb_cc,
708
    gen_op_jz_cc,
709
    gen_op_jbe_cc,
710
    gen_op_js_cc,
711
    gen_op_jp_cc,
712
    gen_op_jl_cc,
713
    gen_op_jle_cc,
714
};
715
    
716
static GenOpFunc2 *gen_jcc_sub[3][8] = {
717
    [OT_BYTE] = {
718
        NULL,
719
        gen_op_jb_subb,
720
        gen_op_jz_subb,
721
        gen_op_jbe_subb,
722
        gen_op_js_subb,
723
        NULL,
724
        gen_op_jl_subb,
725
        gen_op_jle_subb,
726
    },
727
    [OT_WORD] = {
728
        NULL,
729
        gen_op_jb_subw,
730
        gen_op_jz_subw,
731
        gen_op_jbe_subw,
732
        gen_op_js_subw,
733
        NULL,
734
        gen_op_jl_subw,
735
        gen_op_jle_subw,
736
    },
737
    [OT_LONG] = {
738
        NULL,
739
        gen_op_jb_subl,
740
        gen_op_jz_subl,
741
        gen_op_jbe_subl,
742
        gen_op_js_subl,
743
        NULL,
744
        gen_op_jl_subl,
745
        gen_op_jle_subl,
746
    },
747
};
748
static GenOpFunc2 *gen_op_loop[2][4] = {
749
    [0] = {
750
        gen_op_loopnzw,
751
        gen_op_loopzw,
752
        gen_op_loopw,
753
        gen_op_jecxzw,
754
    },
755
    [1] = {
756
        gen_op_loopnzl,
757
        gen_op_loopzl,
758
        gen_op_loopl,
759
        gen_op_jecxzl,
760
    },
761
};
762

    
763
static GenOpFunc *gen_setcc_slow[8] = {
764
    gen_op_seto_T0_cc,
765
    gen_op_setb_T0_cc,
766
    gen_op_setz_T0_cc,
767
    gen_op_setbe_T0_cc,
768
    gen_op_sets_T0_cc,
769
    gen_op_setp_T0_cc,
770
    gen_op_setl_T0_cc,
771
    gen_op_setle_T0_cc,
772
};
773

    
774
static GenOpFunc *gen_setcc_sub[3][8] = {
775
    [OT_BYTE] = {
776
        NULL,
777
        gen_op_setb_T0_subb,
778
        gen_op_setz_T0_subb,
779
        gen_op_setbe_T0_subb,
780
        gen_op_sets_T0_subb,
781
        NULL,
782
        gen_op_setl_T0_subb,
783
        gen_op_setle_T0_subb,
784
    },
785
    [OT_WORD] = {
786
        NULL,
787
        gen_op_setb_T0_subw,
788
        gen_op_setz_T0_subw,
789
        gen_op_setbe_T0_subw,
790
        gen_op_sets_T0_subw,
791
        NULL,
792
        gen_op_setl_T0_subw,
793
        gen_op_setle_T0_subw,
794
    },
795
    [OT_LONG] = {
796
        NULL,
797
        gen_op_setb_T0_subl,
798
        gen_op_setz_T0_subl,
799
        gen_op_setbe_T0_subl,
800
        gen_op_sets_T0_subl,
801
        NULL,
802
        gen_op_setl_T0_subl,
803
        gen_op_setle_T0_subl,
804
    },
805
};
806

    
807
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
808
    gen_op_fadd_ST0_FT0,
809
    gen_op_fmul_ST0_FT0,
810
    gen_op_fcom_ST0_FT0,
811
    gen_op_fcom_ST0_FT0,
812
    gen_op_fsub_ST0_FT0,
813
    gen_op_fsubr_ST0_FT0,
814
    gen_op_fdiv_ST0_FT0,
815
    gen_op_fdivr_ST0_FT0,
816
};
817

    
818
/* NOTE the exception in "r" op ordering */
819
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
820
    gen_op_fadd_STN_ST0,
821
    gen_op_fmul_STN_ST0,
822
    NULL,
823
    NULL,
824
    gen_op_fsubr_STN_ST0,
825
    gen_op_fsub_STN_ST0,
826
    gen_op_fdivr_STN_ST0,
827
    gen_op_fdiv_STN_ST0,
828
};
829

    
830
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
831
{
832
    if (d != OR_TMP0)
833
        gen_op_mov_TN_reg[ot][0][d]();
834
    if (s != OR_TMP1)
835
        gen_op_mov_TN_reg[ot][1][s]();
836
    if (op == OP_ADCL || op == OP_SBBL) {
837
        if (s1->cc_op != CC_OP_DYNAMIC)
838
            gen_op_set_cc_op(s1->cc_op);
839
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
840
        s1->cc_op = CC_OP_DYNAMIC;
841
    } else {
842
        gen_op_arith_T0_T1_cc[op]();
843
        s1->cc_op = cc_op_arithb[op] + ot;
844
    }
845
    if (d != OR_TMP0 && op != OP_CMPL)
846
        gen_op_mov_reg_T0[ot][d]();
847
}
848

    
849
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
850
{
851
    gen_op_movl_T1_im(c);
852
    gen_op(s1, op, ot, d, OR_TMP1);
853
}
854

    
855
static void gen_inc(DisasContext *s1, int ot, int d, int c)
856
{
857
    if (d != OR_TMP0)
858
        gen_op_mov_TN_reg[ot][0][d]();
859
    if (s1->cc_op != CC_OP_DYNAMIC)
860
        gen_op_set_cc_op(s1->cc_op);
861
    if (c > 0) {
862
        gen_op_incl_T0_cc();
863
        s1->cc_op = CC_OP_INCB + ot;
864
    } else {
865
        gen_op_decl_T0_cc();
866
        s1->cc_op = CC_OP_DECB + ot;
867
    }
868
    if (d != OR_TMP0)
869
        gen_op_mov_reg_T0[ot][d]();
870
}
871

    
872
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
873
{
874
    if (d != OR_TMP0)
875
        gen_op_mov_TN_reg[ot][0][d]();
876
    if (s != OR_TMP1)
877
        gen_op_mov_TN_reg[ot][1][s]();
878
    /* for zero counts, flags are not updated, so must do it dynamically */
879
    if (s1->cc_op != CC_OP_DYNAMIC)
880
        gen_op_set_cc_op(s1->cc_op);
881

    
882
    gen_op_shift_T0_T1_cc[ot][op]();
883

    
884
    if (d != OR_TMP0)
885
        gen_op_mov_reg_T0[ot][d]();
886
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
887
}
888

    
889
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
890
{
891
    /* currently not optimized */
892
    gen_op_movl_T1_im(c);
893
    gen_shift(s1, op, ot, d, OR_TMP1);
894
}
895

    
896
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
897
{
898
    int havesib;
899
    int base, disp;
900
    int index;
901
    int scale;
902
    int opreg;
903
    int mod, rm, code, override, must_add_seg;
904

    
905
    override = s->override;
906
    must_add_seg = s->addseg;
907
    if (override >= 0)
908
        must_add_seg = 1;
909
    mod = (modrm >> 6) & 3;
910
    rm = modrm & 7;
911

    
912
    if (s->aflag) {
913

    
914
        havesib = 0;
915
        base = rm;
916
        index = 0;
917
        scale = 0;
918
        
919
        if (base == 4) {
920
            havesib = 1;
921
            code = ldub(s->pc++);
922
            scale = (code >> 6) & 3;
923
            index = (code >> 3) & 7;
924
            base = code & 7;
925
        }
926

    
927
        switch (mod) {
928
        case 0:
929
            if (base == 5) {
930
                base = -1;
931
                disp = ldl(s->pc);
932
                s->pc += 4;
933
            } else {
934
                disp = 0;
935
            }
936
            break;
937
        case 1:
938
            disp = (int8_t)ldub(s->pc++);
939
            break;
940
        default:
941
        case 2:
942
            disp = ldl(s->pc);
943
            s->pc += 4;
944
            break;
945
        }
946
        
947
        if (base >= 0) {
948
            gen_op_movl_A0_reg[base]();
949
            if (disp != 0)
950
                gen_op_addl_A0_im(disp);
951
        } else {
952
            gen_op_movl_A0_im(disp);
953
        }
954
        if (havesib && (index != 4 || scale != 0)) {
955
            gen_op_addl_A0_reg_sN[scale][index]();
956
        }
957
        if (must_add_seg) {
958
            if (override < 0) {
959
                if (base == R_EBP || base == R_ESP)
960
                    override = R_SS;
961
                else
962
                    override = R_DS;
963
            }
964
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
965
        }
966
    } else {
967
        switch (mod) {
968
        case 0:
969
            if (rm == 6) {
970
                disp = lduw(s->pc);
971
                s->pc += 2;
972
                gen_op_movl_A0_im(disp);
973
                rm = 0; /* avoid SS override */
974
                goto no_rm;
975
            } else {
976
                disp = 0;
977
            }
978
            break;
979
        case 1:
980
            disp = (int8_t)ldub(s->pc++);
981
            break;
982
        default:
983
        case 2:
984
            disp = lduw(s->pc);
985
            s->pc += 2;
986
            break;
987
        }
988
        switch(rm) {
989
        case 0:
990
            gen_op_movl_A0_reg[R_EBX]();
991
            gen_op_addl_A0_reg_sN[0][R_ESI]();
992
            break;
993
        case 1:
994
            gen_op_movl_A0_reg[R_EBX]();
995
            gen_op_addl_A0_reg_sN[0][R_EDI]();
996
            break;
997
        case 2:
998
            gen_op_movl_A0_reg[R_EBP]();
999
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1000
            break;
1001
        case 3:
1002
            gen_op_movl_A0_reg[R_EBP]();
1003
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1004
            break;
1005
        case 4:
1006
            gen_op_movl_A0_reg[R_ESI]();
1007
            break;
1008
        case 5:
1009
            gen_op_movl_A0_reg[R_EDI]();
1010
            break;
1011
        case 6:
1012
            gen_op_movl_A0_reg[R_EBP]();
1013
            break;
1014
        default:
1015
        case 7:
1016
            gen_op_movl_A0_reg[R_EBX]();
1017
            break;
1018
        }
1019
        if (disp != 0)
1020
            gen_op_addl_A0_im(disp);
1021
        gen_op_andl_A0_ffff();
1022
    no_rm:
1023
        if (must_add_seg) {
1024
            if (override < 0) {
1025
                if (rm == 2 || rm == 3 || rm == 6)
1026
                    override = R_SS;
1027
                else
1028
                    override = R_DS;
1029
            }
1030
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1031
        }
1032
    }
1033

    
1034
    opreg = OR_A0;
1035
    disp = 0;
1036
    *reg_ptr = opreg;
1037
    *offset_ptr = disp;
1038
}
1039

    
1040
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1041
   OR_TMP0 */
1042
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1043
{
1044
    int mod, rm, opreg, disp;
1045

    
1046
    mod = (modrm >> 6) & 3;
1047
    rm = modrm & 7;
1048
    if (mod == 3) {
1049
        if (is_store) {
1050
            if (reg != OR_TMP0)
1051
                gen_op_mov_TN_reg[ot][0][reg]();
1052
            gen_op_mov_reg_T0[ot][rm]();
1053
        } else {
1054
            gen_op_mov_TN_reg[ot][0][rm]();
1055
            if (reg != OR_TMP0)
1056
                gen_op_mov_reg_T0[ot][reg]();
1057
        }
1058
    } else {
1059
        gen_lea_modrm(s, modrm, &opreg, &disp);
1060
        if (is_store) {
1061
            if (reg != OR_TMP0)
1062
                gen_op_mov_TN_reg[ot][0][reg]();
1063
            gen_op_st_T0_A0[ot]();
1064
        } else {
1065
            gen_op_ld_T0_A0[ot]();
1066
            if (reg != OR_TMP0)
1067
                gen_op_mov_reg_T0[ot][reg]();
1068
        }
1069
    }
1070
}
1071

    
1072
static inline uint32_t insn_get(DisasContext *s, int ot)
1073
{
1074
    uint32_t ret;
1075

    
1076
    switch(ot) {
1077
    case OT_BYTE:
1078
        ret = ldub(s->pc);
1079
        s->pc++;
1080
        break;
1081
    case OT_WORD:
1082
        ret = lduw(s->pc);
1083
        s->pc += 2;
1084
        break;
1085
    default:
1086
    case OT_LONG:
1087
        ret = ldl(s->pc);
1088
        s->pc += 4;
1089
        break;
1090
    }
1091
    return ret;
1092
}
1093

    
1094
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1095
{
1096
    int inv, jcc_op;
1097
    GenOpFunc2 *func;
1098

    
1099
    inv = b & 1;
1100
    jcc_op = (b >> 1) & 7;
1101
    switch(s->cc_op) {
1102
        /* we optimize the cmp/jcc case */
1103
    case CC_OP_SUBB:
1104
    case CC_OP_SUBW:
1105
    case CC_OP_SUBL:
1106
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1107
        if (!func)
1108
            goto slow_jcc;
1109
        break;
1110
        
1111
        /* some jumps are easy to compute */
1112
    case CC_OP_ADDB:
1113
    case CC_OP_ADDW:
1114
    case CC_OP_ADDL:
1115
    case CC_OP_ADCB:
1116
    case CC_OP_ADCW:
1117
    case CC_OP_ADCL:
1118
    case CC_OP_SBBB:
1119
    case CC_OP_SBBW:
1120
    case CC_OP_SBBL:
1121
    case CC_OP_LOGICB:
1122
    case CC_OP_LOGICW:
1123
    case CC_OP_LOGICL:
1124
    case CC_OP_INCB:
1125
    case CC_OP_INCW:
1126
    case CC_OP_INCL:
1127
    case CC_OP_DECB:
1128
    case CC_OP_DECW:
1129
    case CC_OP_DECL:
1130
    case CC_OP_SHLB:
1131
    case CC_OP_SHLW:
1132
    case CC_OP_SHLL:
1133
    case CC_OP_SARB:
1134
    case CC_OP_SARW:
1135
    case CC_OP_SARL:
1136
        switch(jcc_op) {
1137
        case JCC_Z:
1138
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1139
            break;
1140
        case JCC_S:
1141
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1142
            break;
1143
        default:
1144
            goto slow_jcc;
1145
        }
1146
        break;
1147
    default:
1148
    slow_jcc:
1149
        if (s->cc_op != CC_OP_DYNAMIC)
1150
            gen_op_set_cc_op(s->cc_op);
1151
        func = gen_jcc_slow[jcc_op];
1152
        break;
1153
    }
1154
    if (!inv) {
1155
        func(val, next_eip);
1156
    } else {
1157
        func(next_eip, val);
1158
    }
1159
}
1160

    
1161
static void gen_setcc(DisasContext *s, int b)
1162
{
1163
    int inv, jcc_op;
1164
    GenOpFunc *func;
1165

    
1166
    inv = b & 1;
1167
    jcc_op = (b >> 1) & 7;
1168
    switch(s->cc_op) {
1169
        /* we optimize the cmp/jcc case */
1170
    case CC_OP_SUBB:
1171
    case CC_OP_SUBW:
1172
    case CC_OP_SUBL:
1173
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1174
        if (!func)
1175
            goto slow_jcc;
1176
        break;
1177
        
1178
        /* some jumps are easy to compute */
1179
    case CC_OP_ADDB:
1180
    case CC_OP_ADDW:
1181
    case CC_OP_ADDL:
1182
    case CC_OP_LOGICB:
1183
    case CC_OP_LOGICW:
1184
    case CC_OP_LOGICL:
1185
    case CC_OP_INCB:
1186
    case CC_OP_INCW:
1187
    case CC_OP_INCL:
1188
    case CC_OP_DECB:
1189
    case CC_OP_DECW:
1190
    case CC_OP_DECL:
1191
    case CC_OP_SHLB:
1192
    case CC_OP_SHLW:
1193
    case CC_OP_SHLL:
1194
        switch(jcc_op) {
1195
        case JCC_Z:
1196
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1197
            break;
1198
        case JCC_S:
1199
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1200
            break;
1201
        default:
1202
            goto slow_jcc;
1203
        }
1204
        break;
1205
    default:
1206
    slow_jcc:
1207
        if (s->cc_op != CC_OP_DYNAMIC)
1208
            gen_op_set_cc_op(s->cc_op);
1209
        func = gen_setcc_slow[jcc_op];
1210
        break;
1211
    }
1212
    func();
1213
    if (inv) {
1214
        gen_op_xor_T0_1();
1215
    }
1216
}
1217

    
1218
/* move T0 to seg_reg and compute if the CPU state may change */
1219
static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1220
{
1221
    gen_op_movl_seg_T0(seg_reg);
1222
    if (!s->addseg && seg_reg < R_FS)
1223
        s->is_jmp = 2; /* abort translation because the register may
1224
                          have a non zero base */
1225
}
1226

    
1227
/* generate a push. It depends on ss32, addseg and dflag */
1228
static void gen_push_T0(DisasContext *s)
1229
{
1230
    if (s->ss32) {
1231
        if (!s->addseg) {
1232
            if (s->dflag)
1233
                gen_op_pushl_T0();
1234
            else
1235
                gen_op_pushw_T0();
1236
        } else {
1237
            if (s->dflag)
1238
                gen_op_pushl_ss32_T0();
1239
            else
1240
                gen_op_pushw_ss32_T0();
1241
        }
1242
    } else {
1243
        if (s->dflag)
1244
            gen_op_pushl_ss16_T0();
1245
        else
1246
            gen_op_pushw_ss16_T0();
1247
    }
1248
}
1249

    
1250
/* two step pop is necessary for precise exceptions */
1251
static void gen_pop_T0(DisasContext *s)
1252
{
1253
    if (s->ss32) {
1254
        if (!s->addseg) {
1255
            if (s->dflag)
1256
                gen_op_popl_T0();
1257
            else
1258
                gen_op_popw_T0();
1259
        } else {
1260
            if (s->dflag)
1261
                gen_op_popl_ss32_T0();
1262
            else
1263
                gen_op_popw_ss32_T0();
1264
        }
1265
    } else {
1266
        if (s->dflag)
1267
            gen_op_popl_ss16_T0();
1268
        else
1269
            gen_op_popw_ss16_T0();
1270
    }
1271
}
1272

    
1273
static void gen_pop_update(DisasContext *s)
1274
{
1275
    if (s->ss32) {
1276
        if (s->dflag)
1277
            gen_op_addl_ESP_4();
1278
        else
1279
            gen_op_addl_ESP_2();
1280
    } else {
1281
        if (s->dflag)
1282
            gen_op_addw_ESP_4();
1283
        else
1284
            gen_op_addw_ESP_2();
1285
    }
1286
}
1287

    
1288
/* NOTE: wrap around in 16 bit not fully handled */
1289
static void gen_pusha(DisasContext *s)
1290
{
1291
    int i;
1292
    gen_op_movl_A0_ESP();
1293
    gen_op_addl_A0_im(-16 <<  s->dflag);
1294
    if (!s->ss32)
1295
        gen_op_andl_A0_ffff();
1296
    gen_op_movl_T1_A0();
1297
    if (s->addseg)
1298
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1299
    for(i = 0;i < 8; i++) {
1300
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1301
        gen_op_st_T0_A0[OT_WORD + s->dflag]();
1302
        gen_op_addl_A0_im(2 <<  s->dflag);
1303
    }
1304
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1305
}
1306

    
1307
/* NOTE: wrap around in 16 bit not fully handled */
1308
static void gen_popa(DisasContext *s)
1309
{
1310
    int i;
1311
    gen_op_movl_A0_ESP();
1312
    if (!s->ss32)
1313
        gen_op_andl_A0_ffff();
1314
    gen_op_movl_T1_A0();
1315
    gen_op_addl_T1_im(16 <<  s->dflag);
1316
    if (s->addseg)
1317
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1318
    for(i = 0;i < 8; i++) {
1319
        /* ESP is not reloaded */
1320
        if (i != 3) {
1321
            gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1322
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1323
        }
1324
        gen_op_addl_A0_im(2 <<  s->dflag);
1325
    }
1326
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1327
}
1328

    
1329
/* NOTE: wrap around in 16 bit not fully handled */
1330
/* XXX: check this */
1331
static void gen_enter(DisasContext *s, int esp_addend, int level)
1332
{
1333
    int ot, level1, addend, opsize;
1334

    
1335
    ot = s->dflag + OT_WORD;
1336
    level &= 0x1f;
1337
    level1 = level;
1338
    opsize = 2 << s->dflag;
1339

    
1340
    gen_op_movl_A0_ESP();
1341
    gen_op_addl_A0_im(-opsize);
1342
    if (!s->ss32)
1343
        gen_op_andl_A0_ffff();
1344
    gen_op_movl_T1_A0();
1345
    if (s->addseg)
1346
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1347
    /* push bp */
1348
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1349
    gen_op_st_T0_A0[ot]();
1350
    if (level) {
1351
        while (level--) {
1352
            gen_op_addl_A0_im(-opsize);
1353
            gen_op_addl_T0_im(-opsize);
1354
            gen_op_st_T0_A0[ot]();
1355
        }
1356
        gen_op_addl_A0_im(-opsize);
1357
        /* XXX: add st_T1_A0 ? */
1358
        gen_op_movl_T0_T1();
1359
        gen_op_st_T0_A0[ot]();
1360
    }
1361
    gen_op_mov_reg_T1[ot][R_EBP]();
1362
    addend = -esp_addend;
1363
    if (level1)
1364
        addend -= opsize * (level1 + 1);
1365
    gen_op_addl_T1_im(addend);
1366
    gen_op_mov_reg_T1[ot][R_ESP]();
1367
}
1368

    
1369
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1370
   is set to true if the instruction sets the PC (last instruction of
1371
   a basic block) */
1372
long disas_insn(DisasContext *s, uint8_t *pc_start)
1373
{
1374
    int b, prefixes, aflag, dflag;
1375
    int shift, ot;
1376
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1377
    unsigned int next_eip;
1378

    
1379
    s->pc = pc_start;
1380
    prefixes = 0;
1381
    aflag = s->code32;
1382
    dflag = s->code32;
1383
    s->override = -1;
1384
 next_byte:
1385
    b = ldub(s->pc);
1386
    s->pc++;
1387
    /* check prefixes */
1388
    switch (b) {
1389
    case 0xf3:
1390
        prefixes |= PREFIX_REPZ;
1391
        goto next_byte;
1392
    case 0xf2:
1393
        prefixes |= PREFIX_REPNZ;
1394
        goto next_byte;
1395
    case 0xf0:
1396
        prefixes |= PREFIX_LOCK;
1397
        goto next_byte;
1398
    case 0x2e:
1399
        s->override = R_CS;
1400
        goto next_byte;
1401
    case 0x36:
1402
        s->override = R_SS;
1403
        goto next_byte;
1404
    case 0x3e:
1405
        s->override = R_DS;
1406
        goto next_byte;
1407
    case 0x26:
1408
        s->override = R_ES;
1409
        goto next_byte;
1410
    case 0x64:
1411
        s->override = R_FS;
1412
        goto next_byte;
1413
    case 0x65:
1414
        s->override = R_GS;
1415
        goto next_byte;
1416
    case 0x66:
1417
        prefixes |= PREFIX_DATA;
1418
        goto next_byte;
1419
    case 0x67:
1420
        prefixes |= PREFIX_ADR;
1421
        goto next_byte;
1422
    case 0x9b:
1423
        prefixes |= PREFIX_FWAIT;
1424
        goto next_byte;
1425
    }
1426

    
1427
    if (prefixes & PREFIX_DATA)
1428
        dflag ^= 1;
1429
    if (prefixes & PREFIX_ADR)
1430
        aflag ^= 1;
1431

    
1432
    s->prefix = prefixes;
1433
    s->aflag = aflag;
1434
    s->dflag = dflag;
1435

    
1436
    /* lock generation */
1437
    if (prefixes & PREFIX_LOCK)
1438
        gen_op_lock();
1439

    
1440
    /* now check op code */
1441
 reswitch:
1442
    switch(b) {
1443
    case 0x0f:
1444
        /**************************/
1445
        /* extended op code */
1446
        b = ldub(s->pc++) | 0x100;
1447
        goto reswitch;
1448
        
1449
        /**************************/
1450
        /* arith & logic */
1451
    case 0x00 ... 0x05:
1452
    case 0x08 ... 0x0d:
1453
    case 0x10 ... 0x15:
1454
    case 0x18 ... 0x1d:
1455
    case 0x20 ... 0x25:
1456
    case 0x28 ... 0x2d:
1457
    case 0x30 ... 0x35:
1458
    case 0x38 ... 0x3d:
1459
        {
1460
            int op, f, val;
1461
            op = (b >> 3) & 7;
1462
            f = (b >> 1) & 3;
1463

    
1464
            if ((b & 1) == 0)
1465
                ot = OT_BYTE;
1466
            else
1467
                ot = dflag ? OT_LONG : OT_WORD;
1468
            
1469
            switch(f) {
1470
            case 0: /* OP Ev, Gv */
1471
                modrm = ldub(s->pc++);
1472
                reg = ((modrm >> 3) & 7) + OR_EAX;
1473
                mod = (modrm >> 6) & 3;
1474
                rm = modrm & 7;
1475
                if (mod != 3) {
1476
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1477
                    gen_op_ld_T0_A0[ot]();
1478
                    opreg = OR_TMP0;
1479
                } else {
1480
                    opreg = OR_EAX + rm;
1481
                }
1482
                gen_op(s, op, ot, opreg, reg);
1483
                if (mod != 3 && op != 7) {
1484
                    gen_op_st_T0_A0[ot]();
1485
                }
1486
                break;
1487
            case 1: /* OP Gv, Ev */
1488
                modrm = ldub(s->pc++);
1489
                mod = (modrm >> 6) & 3;
1490
                reg = ((modrm >> 3) & 7) + OR_EAX;
1491
                rm = modrm & 7;
1492
                if (mod != 3) {
1493
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1494
                    gen_op_ld_T1_A0[ot]();
1495
                    opreg = OR_TMP1;
1496
                } else {
1497
                    opreg = OR_EAX + rm;
1498
                }
1499
                gen_op(s, op, ot, reg, opreg);
1500
                break;
1501
            case 2: /* OP A, Iv */
1502
                val = insn_get(s, ot);
1503
                gen_opi(s, op, ot, OR_EAX, val);
1504
                break;
1505
            }
1506
        }
1507
        break;
1508

    
1509
    case 0x80: /* GRP1 */
1510
    case 0x81:
1511
    case 0x83:
1512
        {
1513
            int val;
1514

    
1515
            if ((b & 1) == 0)
1516
                ot = OT_BYTE;
1517
            else
1518
                ot = dflag ? OT_LONG : OT_WORD;
1519
            
1520
            modrm = ldub(s->pc++);
1521
            mod = (modrm >> 6) & 3;
1522
            rm = modrm & 7;
1523
            op = (modrm >> 3) & 7;
1524
            
1525
            if (mod != 3) {
1526
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1527
                gen_op_ld_T0_A0[ot]();
1528
                opreg = OR_TMP0;
1529
            } else {
1530
                opreg = rm + OR_EAX;
1531
            }
1532

    
1533
            switch(b) {
1534
            default:
1535
            case 0x80:
1536
            case 0x81:
1537
                val = insn_get(s, ot);
1538
                break;
1539
            case 0x83:
1540
                val = (int8_t)insn_get(s, OT_BYTE);
1541
                break;
1542
            }
1543

    
1544
            gen_opi(s, op, ot, opreg, val);
1545
            if (op != 7 && mod != 3) {
1546
                gen_op_st_T0_A0[ot]();
1547
            }
1548
        }
1549
        break;
1550

    
1551
        /**************************/
1552
        /* inc, dec, and other misc arith */
1553
    case 0x40 ... 0x47: /* inc Gv */
1554
        ot = dflag ? OT_LONG : OT_WORD;
1555
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1556
        break;
1557
    case 0x48 ... 0x4f: /* dec Gv */
1558
        ot = dflag ? OT_LONG : OT_WORD;
1559
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1560
        break;
1561
    case 0xf6: /* GRP3 */
1562
    case 0xf7:
1563
        if ((b & 1) == 0)
1564
            ot = OT_BYTE;
1565
        else
1566
            ot = dflag ? OT_LONG : OT_WORD;
1567

    
1568
        modrm = ldub(s->pc++);
1569
        mod = (modrm >> 6) & 3;
1570
        rm = modrm & 7;
1571
        op = (modrm >> 3) & 7;
1572
        if (mod != 3) {
1573
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1574
            gen_op_ld_T0_A0[ot]();
1575
        } else {
1576
            gen_op_mov_TN_reg[ot][0][rm]();
1577
        }
1578

    
1579
        switch(op) {
1580
        case 0: /* test */
1581
            val = insn_get(s, ot);
1582
            gen_op_movl_T1_im(val);
1583
            gen_op_testl_T0_T1_cc();
1584
            s->cc_op = CC_OP_LOGICB + ot;
1585
            break;
1586
        case 2: /* not */
1587
            gen_op_notl_T0();
1588
            if (mod != 3) {
1589
                gen_op_st_T0_A0[ot]();
1590
            } else {
1591
                gen_op_mov_reg_T0[ot][rm]();
1592
            }
1593
            break;
1594
        case 3: /* neg */
1595
            gen_op_negl_T0_cc();
1596
            if (mod != 3) {
1597
                gen_op_st_T0_A0[ot]();
1598
            } else {
1599
                gen_op_mov_reg_T0[ot][rm]();
1600
            }
1601
            s->cc_op = CC_OP_SUBB + ot;
1602
            break;
1603
        case 4: /* mul */
1604
            switch(ot) {
1605
            case OT_BYTE:
1606
                gen_op_mulb_AL_T0();
1607
                break;
1608
            case OT_WORD:
1609
                gen_op_mulw_AX_T0();
1610
                break;
1611
            default:
1612
            case OT_LONG:
1613
                gen_op_mull_EAX_T0();
1614
                break;
1615
            }
1616
            s->cc_op = CC_OP_MUL;
1617
            break;
1618
        case 5: /* imul */
1619
            switch(ot) {
1620
            case OT_BYTE:
1621
                gen_op_imulb_AL_T0();
1622
                break;
1623
            case OT_WORD:
1624
                gen_op_imulw_AX_T0();
1625
                break;
1626
            default:
1627
            case OT_LONG:
1628
                gen_op_imull_EAX_T0();
1629
                break;
1630
            }
1631
            s->cc_op = CC_OP_MUL;
1632
            break;
1633
        case 6: /* div */
1634
            switch(ot) {
1635
            case OT_BYTE:
1636
                gen_op_divb_AL_T0();
1637
                break;
1638
            case OT_WORD:
1639
                gen_op_divw_AX_T0();
1640
                break;
1641
            default:
1642
            case OT_LONG:
1643
                gen_op_divl_EAX_T0();
1644
                break;
1645
            }
1646
            break;
1647
        case 7: /* idiv */
1648
            switch(ot) {
1649
            case OT_BYTE:
1650
                gen_op_idivb_AL_T0();
1651
                break;
1652
            case OT_WORD:
1653
                gen_op_idivw_AX_T0();
1654
                break;
1655
            default:
1656
            case OT_LONG:
1657
                gen_op_idivl_EAX_T0();
1658
                break;
1659
            }
1660
            break;
1661
        default:
1662
            goto illegal_op;
1663
        }
1664
        break;
1665

    
1666
    case 0xfe: /* GRP4 */
1667
    case 0xff: /* GRP5 */
1668
        if ((b & 1) == 0)
1669
            ot = OT_BYTE;
1670
        else
1671
            ot = dflag ? OT_LONG : OT_WORD;
1672

    
1673
        modrm = ldub(s->pc++);
1674
        mod = (modrm >> 6) & 3;
1675
        rm = modrm & 7;
1676
        op = (modrm >> 3) & 7;
1677
        if (op >= 2 && b == 0xfe) {
1678
            goto illegal_op;
1679
        }
1680
        if (mod != 3) {
1681
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1682
            if (op != 3 && op != 5)
1683
                gen_op_ld_T0_A0[ot]();
1684
        } else {
1685
            gen_op_mov_TN_reg[ot][0][rm]();
1686
        }
1687

    
1688
        switch(op) {
1689
        case 0: /* inc Ev */
1690
            gen_inc(s, ot, OR_TMP0, 1);
1691
            if (mod != 3)
1692
                gen_op_st_T0_A0[ot]();
1693
            else
1694
                gen_op_mov_reg_T0[ot][rm]();
1695
            break;
1696
        case 1: /* dec Ev */
1697
            gen_inc(s, ot, OR_TMP0, -1);
1698
            if (mod != 3)
1699
                gen_op_st_T0_A0[ot]();
1700
            else
1701
                gen_op_mov_reg_T0[ot][rm]();
1702
            break;
1703
        case 2: /* call Ev */
1704
            /* XXX: optimize if memory (no and is necessary) */
1705
            if (s->dflag == 0)
1706
                gen_op_andl_T0_ffff();
1707
            gen_op_jmp_T0();
1708
            next_eip = s->pc - s->cs_base;
1709
            gen_op_movl_T0_im(next_eip);
1710
            gen_push_T0(s);
1711
            s->is_jmp = 1;
1712
            break;
1713
        case 3: /* lcall Ev */
1714
            /* push return segment + offset */
1715
            gen_op_movl_T0_seg(R_CS);
1716
            gen_push_T0(s);
1717
            next_eip = s->pc - s->cs_base;
1718
            gen_op_movl_T0_im(next_eip);
1719
            gen_push_T0(s);
1720

    
1721
            gen_op_ld_T1_A0[ot]();
1722
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1723
            gen_op_lduw_T0_A0();
1724
            gen_movl_seg_T0(s, R_CS);
1725
            gen_op_movl_T0_T1();
1726
            gen_op_jmp_T0();
1727
            s->is_jmp = 1;
1728
            break;
1729
        case 4: /* jmp Ev */
1730
            if (s->dflag == 0)
1731
                gen_op_andl_T0_ffff();
1732
            gen_op_jmp_T0();
1733
            s->is_jmp = 1;
1734
            break;
1735
        case 5: /* ljmp Ev */
1736
            gen_op_ld_T1_A0[ot]();
1737
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1738
            gen_op_lduw_T0_A0();
1739
            gen_movl_seg_T0(s, R_CS);
1740
            gen_op_movl_T0_T1();
1741
            gen_op_jmp_T0();
1742
            s->is_jmp = 1;
1743
            break;
1744
        case 6: /* push Ev */
1745
            gen_push_T0(s);
1746
            break;
1747
        default:
1748
            goto illegal_op;
1749
        }
1750
        break;
1751

    
1752
    case 0x84: /* test Ev, Gv */
1753
    case 0x85: 
1754
        if ((b & 1) == 0)
1755
            ot = OT_BYTE;
1756
        else
1757
            ot = dflag ? OT_LONG : OT_WORD;
1758

    
1759
        modrm = ldub(s->pc++);
1760
        mod = (modrm >> 6) & 3;
1761
        rm = modrm & 7;
1762
        reg = (modrm >> 3) & 7;
1763
        
1764
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1765
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1766
        gen_op_testl_T0_T1_cc();
1767
        s->cc_op = CC_OP_LOGICB + ot;
1768
        break;
1769
        
1770
    case 0xa8: /* test eAX, Iv */
1771
    case 0xa9:
1772
        if ((b & 1) == 0)
1773
            ot = OT_BYTE;
1774
        else
1775
            ot = dflag ? OT_LONG : OT_WORD;
1776
        val = insn_get(s, ot);
1777

    
1778
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1779
        gen_op_movl_T1_im(val);
1780
        gen_op_testl_T0_T1_cc();
1781
        s->cc_op = CC_OP_LOGICB + ot;
1782
        break;
1783
        
1784
    case 0x98: /* CWDE/CBW */
1785
        if (dflag)
1786
            gen_op_movswl_EAX_AX();
1787
        else
1788
            gen_op_movsbw_AX_AL();
1789
        break;
1790
    case 0x99: /* CDQ/CWD */
1791
        if (dflag)
1792
            gen_op_movslq_EDX_EAX();
1793
        else
1794
            gen_op_movswl_DX_AX();
1795
        break;
1796
    case 0x1af: /* imul Gv, Ev */
1797
    case 0x69: /* imul Gv, Ev, I */
1798
    case 0x6b:
1799
        ot = dflag ? OT_LONG : OT_WORD;
1800
        modrm = ldub(s->pc++);
1801
        reg = ((modrm >> 3) & 7) + OR_EAX;
1802
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1803
        if (b == 0x69) {
1804
            val = insn_get(s, ot);
1805
            gen_op_movl_T1_im(val);
1806
        } else if (b == 0x6b) {
1807
            val = insn_get(s, OT_BYTE);
1808
            gen_op_movl_T1_im(val);
1809
        } else {
1810
            gen_op_mov_TN_reg[ot][1][reg]();
1811
        }
1812

    
1813
        if (ot == OT_LONG) {
1814
            gen_op_imull_T0_T1();
1815
        } else {
1816
            gen_op_imulw_T0_T1();
1817
        }
1818
        gen_op_mov_reg_T0[ot][reg]();
1819
        s->cc_op = CC_OP_MUL;
1820
        break;
1821
    case 0x1c0:
1822
    case 0x1c1: /* xadd Ev, Gv */
1823
        if ((b & 1) == 0)
1824
            ot = OT_BYTE;
1825
        else
1826
            ot = dflag ? OT_LONG : OT_WORD;
1827
        modrm = ldub(s->pc++);
1828
        reg = (modrm >> 3) & 7;
1829
        mod = (modrm >> 6) & 3;
1830
        if (mod == 3) {
1831
            rm = modrm & 7;
1832
            gen_op_mov_TN_reg[ot][0][reg]();
1833
            gen_op_mov_TN_reg[ot][1][rm]();
1834
            gen_op_addl_T0_T1_cc();
1835
            gen_op_mov_reg_T0[ot][rm]();
1836
            gen_op_mov_reg_T1[ot][reg]();
1837
        } else {
1838
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1839
            gen_op_mov_TN_reg[ot][0][reg]();
1840
            gen_op_ld_T1_A0[ot]();
1841
            gen_op_addl_T0_T1_cc();
1842
            gen_op_st_T0_A0[ot]();
1843
            gen_op_mov_reg_T1[ot][reg]();
1844
        }
1845
        s->cc_op = CC_OP_ADDB + ot;
1846
        break;
1847
    case 0x1b0:
1848
    case 0x1b1: /* cmpxchg Ev, Gv */
1849
        if ((b & 1) == 0)
1850
            ot = OT_BYTE;
1851
        else
1852
            ot = dflag ? OT_LONG : OT_WORD;
1853
        modrm = ldub(s->pc++);
1854
        reg = (modrm >> 3) & 7;
1855
        mod = (modrm >> 6) & 3;
1856
        gen_op_mov_TN_reg[ot][1][reg]();
1857
        if (mod == 3) {
1858
            rm = modrm & 7;
1859
            gen_op_mov_TN_reg[ot][0][rm]();
1860
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1861
            gen_op_mov_reg_T0[ot][rm]();
1862
        } else {
1863
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1864
            gen_op_ld_T0_A0[ot]();
1865
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1866
            gen_op_st_T0_A0[ot]();
1867
        }
1868
        s->cc_op = CC_OP_SUBB + ot;
1869
        break;
1870
    case 0x1c7: /* cmpxchg8b */
1871
        modrm = ldub(s->pc++);
1872
        mod = (modrm >> 6) & 3;
1873
        if (mod == 3)
1874
            goto illegal_op;
1875
        if (s->cc_op != CC_OP_DYNAMIC)
1876
            gen_op_set_cc_op(s->cc_op);
1877
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1878
        gen_op_cmpxchg8b();
1879
        s->cc_op = CC_OP_EFLAGS;
1880
        break;
1881
        
1882
        /**************************/
1883
        /* push/pop */
1884
    case 0x50 ... 0x57: /* push */
1885
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1886
        gen_push_T0(s);
1887
        break;
1888
    case 0x58 ... 0x5f: /* pop */
1889
        ot = dflag ? OT_LONG : OT_WORD;
1890
        gen_pop_T0(s);
1891
        gen_op_mov_reg_T0[ot][b & 7]();
1892
        gen_pop_update(s);
1893
        break;
1894
    case 0x60: /* pusha */
1895
        gen_pusha(s);
1896
        break;
1897
    case 0x61: /* popa */
1898
        gen_popa(s);
1899
        break;
1900
    case 0x68: /* push Iv */
1901
    case 0x6a:
1902
        ot = dflag ? OT_LONG : OT_WORD;
1903
        if (b == 0x68)
1904
            val = insn_get(s, ot);
1905
        else
1906
            val = (int8_t)insn_get(s, OT_BYTE);
1907
        gen_op_movl_T0_im(val);
1908
        gen_push_T0(s);
1909
        break;
1910
    case 0x8f: /* pop Ev */
1911
        ot = dflag ? OT_LONG : OT_WORD;
1912
        modrm = ldub(s->pc++);
1913
        gen_pop_T0(s);
1914
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1915
        gen_pop_update(s);
1916
        break;
1917
    case 0xc8: /* enter */
1918
        {
1919
            int level;
1920
            val = lduw(s->pc);
1921
            s->pc += 2;
1922
            level = ldub(s->pc++);
1923
            gen_enter(s, val, level);
1924
        }
1925
        break;
1926
    case 0xc9: /* leave */
1927
        /* XXX: exception not precise (ESP is update before potential exception) */
1928
        if (s->ss32) {
1929
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1930
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1931
        } else {
1932
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1933
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1934
        }
1935
        gen_pop_T0(s);
1936
        ot = dflag ? OT_LONG : OT_WORD;
1937
        gen_op_mov_reg_T0[ot][R_EBP]();
1938
        gen_pop_update(s);
1939
        break;
1940
    case 0x06: /* push es */
1941
    case 0x0e: /* push cs */
1942
    case 0x16: /* push ss */
1943
    case 0x1e: /* push ds */
1944
        gen_op_movl_T0_seg(b >> 3);
1945
        gen_push_T0(s);
1946
        break;
1947
    case 0x1a0: /* push fs */
1948
    case 0x1a8: /* push gs */
1949
        gen_op_movl_T0_seg((b >> 3) & 7);
1950
        gen_push_T0(s);
1951
        break;
1952
    case 0x07: /* pop es */
1953
    case 0x17: /* pop ss */
1954
    case 0x1f: /* pop ds */
1955
        gen_pop_T0(s);
1956
        gen_movl_seg_T0(s, b >> 3);
1957
        gen_pop_update(s);
1958
        break;
1959
    case 0x1a1: /* pop fs */
1960
    case 0x1a9: /* pop gs */
1961
        gen_pop_T0(s);
1962
        gen_movl_seg_T0(s, (b >> 3) & 7);
1963
        gen_pop_update(s);
1964
        break;
1965

    
1966
        /**************************/
1967
        /* mov */
1968
    case 0x88:
1969
    case 0x89: /* mov Gv, Ev */
1970
        if ((b & 1) == 0)
1971
            ot = OT_BYTE;
1972
        else
1973
            ot = dflag ? OT_LONG : OT_WORD;
1974
        modrm = ldub(s->pc++);
1975
        reg = (modrm >> 3) & 7;
1976
        
1977
        /* generate a generic store */
1978
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1979
        break;
1980
    case 0xc6:
1981
    case 0xc7: /* mov Ev, Iv */
1982
        if ((b & 1) == 0)
1983
            ot = OT_BYTE;
1984
        else
1985
            ot = dflag ? OT_LONG : OT_WORD;
1986
        modrm = ldub(s->pc++);
1987
        mod = (modrm >> 6) & 3;
1988
        if (mod != 3)
1989
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1990
        val = insn_get(s, ot);
1991
        gen_op_movl_T0_im(val);
1992
        if (mod != 3)
1993
            gen_op_st_T0_A0[ot]();
1994
        else
1995
            gen_op_mov_reg_T0[ot][modrm & 7]();
1996
        break;
1997
    case 0x8a:
1998
    case 0x8b: /* mov Ev, Gv */
1999
        if ((b & 1) == 0)
2000
            ot = OT_BYTE;
2001
        else
2002
            ot = dflag ? OT_LONG : OT_WORD;
2003
        modrm = ldub(s->pc++);
2004
        reg = (modrm >> 3) & 7;
2005
        
2006
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2007
        gen_op_mov_reg_T0[ot][reg]();
2008
        break;
2009
    case 0x8e: /* mov seg, Gv */
2010
        ot = dflag ? OT_LONG : OT_WORD;
2011
        modrm = ldub(s->pc++);
2012
        reg = (modrm >> 3) & 7;
2013
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2014
        if (reg >= 6 || reg == R_CS)
2015
            goto illegal_op;
2016
        gen_movl_seg_T0(s, reg);
2017
        break;
2018
    case 0x8c: /* mov Gv, seg */
2019
        ot = dflag ? OT_LONG : OT_WORD;
2020
        modrm = ldub(s->pc++);
2021
        reg = (modrm >> 3) & 7;
2022
        if (reg >= 6)
2023
            goto illegal_op;
2024
        gen_op_movl_T0_seg(reg);
2025
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2026
        break;
2027

    
2028
    case 0x1b6: /* movzbS Gv, Eb */
2029
    case 0x1b7: /* movzwS Gv, Eb */
2030
    case 0x1be: /* movsbS Gv, Eb */
2031
    case 0x1bf: /* movswS Gv, Eb */
2032
        {
2033
            int d_ot;
2034
            /* d_ot is the size of destination */
2035
            d_ot = dflag + OT_WORD;
2036
            /* ot is the size of source */
2037
            ot = (b & 1) + OT_BYTE;
2038
            modrm = ldub(s->pc++);
2039
            reg = ((modrm >> 3) & 7) + OR_EAX;
2040
            mod = (modrm >> 6) & 3;
2041
            rm = modrm & 7;
2042
            
2043
            if (mod == 3) {
2044
                gen_op_mov_TN_reg[ot][0][rm]();
2045
                switch(ot | (b & 8)) {
2046
                case OT_BYTE:
2047
                    gen_op_movzbl_T0_T0();
2048
                    break;
2049
                case OT_BYTE | 8:
2050
                    gen_op_movsbl_T0_T0();
2051
                    break;
2052
                case OT_WORD:
2053
                    gen_op_movzwl_T0_T0();
2054
                    break;
2055
                default:
2056
                case OT_WORD | 8:
2057
                    gen_op_movswl_T0_T0();
2058
                    break;
2059
                }
2060
                gen_op_mov_reg_T0[d_ot][reg]();
2061
            } else {
2062
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2063
                if (b & 8) {
2064
                    gen_op_lds_T0_A0[ot]();
2065
                } else {
2066
                    gen_op_ldu_T0_A0[ot]();
2067
                }
2068
                gen_op_mov_reg_T0[d_ot][reg]();
2069
            }
2070
        }
2071
        break;
2072

    
2073
    case 0x8d: /* lea */
2074
        ot = dflag ? OT_LONG : OT_WORD;
2075
        modrm = ldub(s->pc++);
2076
        reg = (modrm >> 3) & 7;
2077
        /* we must ensure that no segment is added */
2078
        s->override = -1;
2079
        val = s->addseg;
2080
        s->addseg = 0;
2081
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2082
        s->addseg = val;
2083
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2084
        break;
2085
        
2086
    case 0xa0: /* mov EAX, Ov */
2087
    case 0xa1:
2088
    case 0xa2: /* mov Ov, EAX */
2089
    case 0xa3:
2090
        if ((b & 1) == 0)
2091
            ot = OT_BYTE;
2092
        else
2093
            ot = dflag ? OT_LONG : OT_WORD;
2094
        if (s->aflag)
2095
            offset_addr = insn_get(s, OT_LONG);
2096
        else
2097
            offset_addr = insn_get(s, OT_WORD);
2098
        gen_op_movl_A0_im(offset_addr);
2099
        /* handle override */
2100
        {
2101
            int override, must_add_seg;
2102
            must_add_seg = s->addseg;
2103
            if (s->override >= 0) {
2104
                override = s->override;
2105
                must_add_seg = 1;
2106
            } else {
2107
                override = R_DS;
2108
            }
2109
            if (must_add_seg) {
2110
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2111
            }
2112
        }
2113
        if ((b & 2) == 0) {
2114
            gen_op_ld_T0_A0[ot]();
2115
            gen_op_mov_reg_T0[ot][R_EAX]();
2116
        } else {
2117
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2118
            gen_op_st_T0_A0[ot]();
2119
        }
2120
        break;
2121
    case 0xd7: /* xlat */
2122
        gen_op_movl_A0_reg[R_EBX]();
2123
        gen_op_addl_A0_AL();
2124
        if (s->aflag == 0)
2125
            gen_op_andl_A0_ffff();
2126
        /* handle override */
2127
        {
2128
            int override, must_add_seg;
2129
            must_add_seg = s->addseg;
2130
            override = R_DS;
2131
            if (s->override >= 0) {
2132
                override = s->override;
2133
                must_add_seg = 1;
2134
            } else {
2135
                override = R_DS;
2136
            }
2137
            if (must_add_seg) {
2138
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2139
            }
2140
        }
2141
        gen_op_ldub_T0_A0();
2142
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2143
        break;
2144
    case 0xb0 ... 0xb7: /* mov R, Ib */
2145
        val = insn_get(s, OT_BYTE);
2146
        gen_op_movl_T0_im(val);
2147
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2148
        break;
2149
    case 0xb8 ... 0xbf: /* mov R, Iv */
2150
        ot = dflag ? OT_LONG : OT_WORD;
2151
        val = insn_get(s, ot);
2152
        reg = OR_EAX + (b & 7);
2153
        gen_op_movl_T0_im(val);
2154
        gen_op_mov_reg_T0[ot][reg]();
2155
        break;
2156

    
2157
    case 0x91 ... 0x97: /* xchg R, EAX */
2158
        ot = dflag ? OT_LONG : OT_WORD;
2159
        reg = b & 7;
2160
        rm = R_EAX;
2161
        goto do_xchg_reg;
2162
    case 0x86:
2163
    case 0x87: /* xchg Ev, Gv */
2164
        if ((b & 1) == 0)
2165
            ot = OT_BYTE;
2166
        else
2167
            ot = dflag ? OT_LONG : OT_WORD;
2168
        modrm = ldub(s->pc++);
2169
        reg = (modrm >> 3) & 7;
2170
        mod = (modrm >> 6) & 3;
2171
        if (mod == 3) {
2172
            rm = modrm & 7;
2173
        do_xchg_reg:
2174
            gen_op_mov_TN_reg[ot][0][reg]();
2175
            gen_op_mov_TN_reg[ot][1][rm]();
2176
            gen_op_mov_reg_T0[ot][rm]();
2177
            gen_op_mov_reg_T1[ot][reg]();
2178
        } else {
2179
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2180
            gen_op_mov_TN_reg[ot][0][reg]();
2181
            /* for xchg, lock is implicit */
2182
            if (!(prefixes & PREFIX_LOCK))
2183
                gen_op_lock();
2184
            gen_op_ld_T1_A0[ot]();
2185
            gen_op_st_T0_A0[ot]();
2186
            if (!(prefixes & PREFIX_LOCK))
2187
                gen_op_unlock();
2188
            gen_op_mov_reg_T1[ot][reg]();
2189
        }
2190
        break;
2191
    case 0xc4: /* les Gv */
2192
        op = R_ES;
2193
        goto do_lxx;
2194
    case 0xc5: /* lds Gv */
2195
        op = R_DS;
2196
        goto do_lxx;
2197
    case 0x1b2: /* lss Gv */
2198
        op = R_SS;
2199
        goto do_lxx;
2200
    case 0x1b4: /* lfs Gv */
2201
        op = R_FS;
2202
        goto do_lxx;
2203
    case 0x1b5: /* lgs Gv */
2204
        op = R_GS;
2205
    do_lxx:
2206
        ot = dflag ? OT_LONG : OT_WORD;
2207
        modrm = ldub(s->pc++);
2208
        reg = (modrm >> 3) & 7;
2209
        mod = (modrm >> 6) & 3;
2210
        if (mod == 3)
2211
            goto illegal_op;
2212
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2213
        gen_op_ld_T1_A0[ot]();
2214
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2215
        /* load the segment first to handle exceptions properly */
2216
        gen_op_lduw_T0_A0();
2217
        gen_movl_seg_T0(s, op);
2218
        /* then put the data */
2219
        gen_op_mov_reg_T1[ot][reg]();
2220
        break;
2221
        
2222
        /************************/
2223
        /* shifts */
2224
    case 0xc0:
2225
    case 0xc1:
2226
        /* shift Ev,Ib */
2227
        shift = 2;
2228
    grp2:
2229
        {
2230
            if ((b & 1) == 0)
2231
                ot = OT_BYTE;
2232
            else
2233
                ot = dflag ? OT_LONG : OT_WORD;
2234
            
2235
            modrm = ldub(s->pc++);
2236
            mod = (modrm >> 6) & 3;
2237
            rm = modrm & 7;
2238
            op = (modrm >> 3) & 7;
2239
            
2240
            if (mod != 3) {
2241
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2242
                gen_op_ld_T0_A0[ot]();
2243
                opreg = OR_TMP0;
2244
            } else {
2245
                opreg = rm + OR_EAX;
2246
            }
2247

    
2248
            /* simpler op */
2249
            if (shift == 0) {
2250
                gen_shift(s, op, ot, opreg, OR_ECX);
2251
            } else {
2252
                if (shift == 2) {
2253
                    shift = ldub(s->pc++);
2254
                }
2255
                gen_shifti(s, op, ot, opreg, shift);
2256
            }
2257

    
2258
            if (mod != 3) {
2259
                gen_op_st_T0_A0[ot]();
2260
            }
2261
        }
2262
        break;
2263
    case 0xd0:
2264
    case 0xd1:
2265
        /* shift Ev,1 */
2266
        shift = 1;
2267
        goto grp2;
2268
    case 0xd2:
2269
    case 0xd3:
2270
        /* shift Ev,cl */
2271
        shift = 0;
2272
        goto grp2;
2273

    
2274
    case 0x1a4: /* shld imm */
2275
        op = 0;
2276
        shift = 1;
2277
        goto do_shiftd;
2278
    case 0x1a5: /* shld cl */
2279
        op = 0;
2280
        shift = 0;
2281
        goto do_shiftd;
2282
    case 0x1ac: /* shrd imm */
2283
        op = 1;
2284
        shift = 1;
2285
        goto do_shiftd;
2286
    case 0x1ad: /* shrd cl */
2287
        op = 1;
2288
        shift = 0;
2289
    do_shiftd:
2290
        ot = dflag ? OT_LONG : OT_WORD;
2291
        modrm = ldub(s->pc++);
2292
        mod = (modrm >> 6) & 3;
2293
        rm = modrm & 7;
2294
        reg = (modrm >> 3) & 7;
2295
        
2296
        if (mod != 3) {
2297
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2298
            gen_op_ld_T0_A0[ot]();
2299
        } else {
2300
            gen_op_mov_TN_reg[ot][0][rm]();
2301
        }
2302
        gen_op_mov_TN_reg[ot][1][reg]();
2303
        
2304
        if (shift) {
2305
            val = ldub(s->pc++);
2306
            val &= 0x1f;
2307
            if (val) {
2308
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2309
                if (op == 0 && ot != OT_WORD)
2310
                    s->cc_op = CC_OP_SHLB + ot;
2311
                else
2312
                    s->cc_op = CC_OP_SARB + ot;
2313
            }
2314
        } else {
2315
            if (s->cc_op != CC_OP_DYNAMIC)
2316
                gen_op_set_cc_op(s->cc_op);
2317
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2318
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2319
        }
2320
        if (mod != 3) {
2321
            gen_op_st_T0_A0[ot]();
2322
        } else {
2323
            gen_op_mov_reg_T0[ot][rm]();
2324
        }
2325
        break;
2326

    
2327
        /************************/
2328
        /* floats */
2329
    case 0xd8 ... 0xdf: 
2330
        modrm = ldub(s->pc++);
2331
        mod = (modrm >> 6) & 3;
2332
        rm = modrm & 7;
2333
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2334
        
2335
        if (mod != 3) {
2336
            /* memory op */
2337
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2338
            switch(op) {
2339
            case 0x00 ... 0x07: /* fxxxs */
2340
            case 0x10 ... 0x17: /* fixxxl */
2341
            case 0x20 ... 0x27: /* fxxxl */
2342
            case 0x30 ... 0x37: /* fixxx */
2343
                {
2344
                    int op1;
2345
                    op1 = op & 7;
2346

    
2347
                    switch(op >> 4) {
2348
                    case 0:
2349
                        gen_op_flds_FT0_A0();
2350
                        break;
2351
                    case 1:
2352
                        gen_op_fildl_FT0_A0();
2353
                        break;
2354
                    case 2:
2355
                        gen_op_fldl_FT0_A0();
2356
                        break;
2357
                    case 3:
2358
                    default:
2359
                        gen_op_fild_FT0_A0();
2360
                        break;
2361
                    }
2362
                    
2363
                    gen_op_fp_arith_ST0_FT0[op1]();
2364
                    if (op1 == 3) {
2365
                        /* fcomp needs pop */
2366
                        gen_op_fpop();
2367
                    }
2368
                }
2369
                break;
2370
            case 0x08: /* flds */
2371
            case 0x0a: /* fsts */
2372
            case 0x0b: /* fstps */
2373
            case 0x18: /* fildl */
2374
            case 0x1a: /* fistl */
2375
            case 0x1b: /* fistpl */
2376
            case 0x28: /* fldl */
2377
            case 0x2a: /* fstl */
2378
            case 0x2b: /* fstpl */
2379
            case 0x38: /* filds */
2380
            case 0x3a: /* fists */
2381
            case 0x3b: /* fistps */
2382
                
2383
                switch(op & 7) {
2384
                case 0:
2385
                    gen_op_fpush();
2386
                    switch(op >> 4) {
2387
                    case 0:
2388
                        gen_op_flds_ST0_A0();
2389
                        break;
2390
                    case 1:
2391
                        gen_op_fildl_ST0_A0();
2392
                        break;
2393
                    case 2:
2394
                        gen_op_fldl_ST0_A0();
2395
                        break;
2396
                    case 3:
2397
                    default:
2398
                        gen_op_fild_ST0_A0();
2399
                        break;
2400
                    }
2401
                    break;
2402
                default:
2403
                    switch(op >> 4) {
2404
                    case 0:
2405
                        gen_op_fsts_ST0_A0();
2406
                        break;
2407
                    case 1:
2408
                        gen_op_fistl_ST0_A0();
2409
                        break;
2410
                    case 2:
2411
                        gen_op_fstl_ST0_A0();
2412
                        break;
2413
                    case 3:
2414
                    default:
2415
                        gen_op_fist_ST0_A0();
2416
                        break;
2417
                    }
2418
                    if ((op & 7) == 3)
2419
                        gen_op_fpop();
2420
                    break;
2421
                }
2422
                break;
2423
            case 0x0d: /* fldcw mem */
2424
                gen_op_fldcw_A0();
2425
                break;
2426
            case 0x0f: /* fnstcw mem */
2427
                gen_op_fnstcw_A0();
2428
                break;
2429
            case 0x1d: /* fldt mem */
2430
                gen_op_fpush();
2431
                gen_op_fldt_ST0_A0();
2432
                break;
2433
            case 0x1f: /* fstpt mem */
2434
                gen_op_fstt_ST0_A0();
2435
                gen_op_fpop();
2436
                break;
2437
            case 0x2f: /* fnstsw mem */
2438
                gen_op_fnstsw_A0();
2439
                break;
2440
            case 0x3c: /* fbld */
2441
                gen_op_fpush();
2442
                gen_op_fbld_ST0_A0();
2443
                break;
2444
            case 0x3e: /* fbstp */
2445
                gen_op_fbst_ST0_A0();
2446
                gen_op_fpop();
2447
                break;
2448
            case 0x3d: /* fildll */
2449
                gen_op_fpush();
2450
                gen_op_fildll_ST0_A0();
2451
                break;
2452
            case 0x3f: /* fistpll */
2453
                gen_op_fistll_ST0_A0();
2454
                gen_op_fpop();
2455
                break;
2456
            default:
2457
                goto illegal_op;
2458
            }
2459
        } else {
2460
            /* register float ops */
2461
            opreg = rm;
2462

    
2463
            switch(op) {
2464
            case 0x08: /* fld sti */
2465
                gen_op_fpush();
2466
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2467
                break;
2468
            case 0x09: /* fxchg sti */
2469
                gen_op_fxchg_ST0_STN(opreg);
2470
                break;
2471
            case 0x0a: /* grp d9/2 */
2472
                switch(rm) {
2473
                case 0: /* fnop */
2474
                    break;
2475
                default:
2476
                    goto illegal_op;
2477
                }
2478
                break;
2479
            case 0x0c: /* grp d9/4 */
2480
                switch(rm) {
2481
                case 0: /* fchs */
2482
                    gen_op_fchs_ST0();
2483
                    break;
2484
                case 1: /* fabs */
2485
                    gen_op_fabs_ST0();
2486
                    break;
2487
                case 4: /* ftst */
2488
                    gen_op_fldz_FT0();
2489
                    gen_op_fcom_ST0_FT0();
2490
                    break;
2491
                case 5: /* fxam */
2492
                    gen_op_fxam_ST0();
2493
                    break;
2494
                default:
2495
                    goto illegal_op;
2496
                }
2497
                break;
2498
            case 0x0d: /* grp d9/5 */
2499
                {
2500
                    switch(rm) {
2501
                    case 0:
2502
                        gen_op_fpush();
2503
                        gen_op_fld1_ST0();
2504
                        break;
2505
                    case 1:
2506
                        gen_op_fpush();
2507
                        gen_op_fldl2t_ST0();
2508
                        break;
2509
                    case 2:
2510
                        gen_op_fpush();
2511
                        gen_op_fldl2e_ST0();
2512
                        break;
2513
                    case 3:
2514
                        gen_op_fpush();
2515
                        gen_op_fldpi_ST0();
2516
                        break;
2517
                    case 4:
2518
                        gen_op_fpush();
2519
                        gen_op_fldlg2_ST0();
2520
                        break;
2521
                    case 5:
2522
                        gen_op_fpush();
2523
                        gen_op_fldln2_ST0();
2524
                        break;
2525
                    case 6:
2526
                        gen_op_fpush();
2527
                        gen_op_fldz_ST0();
2528
                        break;
2529
                    default:
2530
                        goto illegal_op;
2531
                    }
2532
                }
2533
                break;
2534
            case 0x0e: /* grp d9/6 */
2535
                switch(rm) {
2536
                case 0: /* f2xm1 */
2537
                    gen_op_f2xm1();
2538
                    break;
2539
                case 1: /* fyl2x */
2540
                    gen_op_fyl2x();
2541
                    break;
2542
                case 2: /* fptan */
2543
                    gen_op_fptan();
2544
                    break;
2545
                case 3: /* fpatan */
2546
                    gen_op_fpatan();
2547
                    break;
2548
                case 4: /* fxtract */
2549
                    gen_op_fxtract();
2550
                    break;
2551
                case 5: /* fprem1 */
2552
                    gen_op_fprem1();
2553
                    break;
2554
                case 6: /* fdecstp */
2555
                    gen_op_fdecstp();
2556
                    break;
2557
                default:
2558
                case 7: /* fincstp */
2559
                    gen_op_fincstp();
2560
                    break;
2561
                }
2562
                break;
2563
            case 0x0f: /* grp d9/7 */
2564
                switch(rm) {
2565
                case 0: /* fprem */
2566
                    gen_op_fprem();
2567
                    break;
2568
                case 1: /* fyl2xp1 */
2569
                    gen_op_fyl2xp1();
2570
                    break;
2571
                case 2: /* fsqrt */
2572
                    gen_op_fsqrt();
2573
                    break;
2574
                case 3: /* fsincos */
2575
                    gen_op_fsincos();
2576
                    break;
2577
                case 5: /* fscale */
2578
                    gen_op_fscale();
2579
                    break;
2580
                case 4: /* frndint */
2581
                    gen_op_frndint();
2582
                    break;
2583
                case 6: /* fsin */
2584
                    gen_op_fsin();
2585
                    break;
2586
                default:
2587
                case 7: /* fcos */
2588
                    gen_op_fcos();
2589
                    break;
2590
                }
2591
                break;
2592
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2593
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2594
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2595
                {
2596
                    int op1;
2597
                    
2598
                    op1 = op & 7;
2599
                    if (op >= 0x20) {
2600
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2601
                        if (op >= 0x30)
2602
                            gen_op_fpop();
2603
                    } else {
2604
                        gen_op_fmov_FT0_STN(opreg);
2605
                        gen_op_fp_arith_ST0_FT0[op1]();
2606
                    }
2607
                }
2608
                break;
2609
            case 0x02: /* fcom */
2610
                gen_op_fmov_FT0_STN(opreg);
2611
                gen_op_fcom_ST0_FT0();
2612
                break;
2613
            case 0x03: /* fcomp */
2614
                gen_op_fmov_FT0_STN(opreg);
2615
                gen_op_fcom_ST0_FT0();
2616
                gen_op_fpop();
2617
                break;
2618
            case 0x15: /* da/5 */
2619
                switch(rm) {
2620
                case 1: /* fucompp */
2621
                    gen_op_fmov_FT0_STN(1);
2622
                    gen_op_fucom_ST0_FT0();
2623
                    gen_op_fpop();
2624
                    gen_op_fpop();
2625
                    break;
2626
                default:
2627
                    goto illegal_op;
2628
                }
2629
                break;
2630
            case 0x1c:
2631
                switch(rm) {
2632
                case 2: /* fclex */
2633
                    gen_op_fclex();
2634
                    break;
2635
                case 3: /* fninit */
2636
                    gen_op_fninit();
2637
                    break;
2638
                default:
2639
                    goto illegal_op;
2640
                }
2641
                break;
2642
            case 0x2a: /* fst sti */
2643
                gen_op_fmov_STN_ST0(opreg);
2644
                break;
2645
            case 0x2b: /* fstp sti */
2646
                gen_op_fmov_STN_ST0(opreg);
2647
                gen_op_fpop();
2648
                break;
2649
            case 0x2c: /* fucom st(i) */
2650
                gen_op_fmov_FT0_STN(opreg);
2651
                gen_op_fucom_ST0_FT0();
2652
                break;
2653
            case 0x2d: /* fucomp st(i) */
2654
                gen_op_fmov_FT0_STN(opreg);
2655
                gen_op_fucom_ST0_FT0();
2656
                gen_op_fpop();
2657
                break;
2658
            case 0x33: /* de/3 */
2659
                switch(rm) {
2660
                case 1: /* fcompp */
2661
                    gen_op_fmov_FT0_STN(1);
2662
                    gen_op_fcom_ST0_FT0();
2663
                    gen_op_fpop();
2664
                    gen_op_fpop();
2665
                    break;
2666
                default:
2667
                    goto illegal_op;
2668
                }
2669
                break;
2670
            case 0x3c: /* df/4 */
2671
                switch(rm) {
2672
                case 0:
2673
                    gen_op_fnstsw_EAX();
2674
                    break;
2675
                default:
2676
                    goto illegal_op;
2677
                }
2678
                break;
2679
            default:
2680
                goto illegal_op;
2681
            }
2682
        }
2683
        break;
2684
        /************************/
2685
        /* string ops */
2686

    
2687
    case 0xa4: /* movsS */
2688
    case 0xa5:
2689
        if ((b & 1) == 0)
2690
            ot = OT_BYTE;
2691
        else
2692
            ot = dflag ? OT_LONG : OT_WORD;
2693

    
2694
        if (prefixes & PREFIX_REPZ) {
2695
            gen_string_ds(s, ot, gen_op_movs + 9);
2696
        } else {
2697
            gen_string_ds(s, ot, gen_op_movs);
2698
        }
2699
        break;
2700
        
2701
    case 0xaa: /* stosS */
2702
    case 0xab:
2703
        if ((b & 1) == 0)
2704
            ot = OT_BYTE;
2705
        else
2706
            ot = dflag ? OT_LONG : OT_WORD;
2707

    
2708
        if (prefixes & PREFIX_REPZ) {
2709
            gen_string_es(s, ot, gen_op_stos + 9);
2710
        } else {
2711
            gen_string_es(s, ot, gen_op_stos);
2712
        }
2713
        break;
2714
    case 0xac: /* lodsS */
2715
    case 0xad:
2716
        if ((b & 1) == 0)
2717
            ot = OT_BYTE;
2718
        else
2719
            ot = dflag ? OT_LONG : OT_WORD;
2720
        if (prefixes & PREFIX_REPZ) {
2721
            gen_string_ds(s, ot, gen_op_lods + 9);
2722
        } else {
2723
            gen_string_ds(s, ot, gen_op_lods);
2724
        }
2725
        break;
2726
    case 0xae: /* scasS */
2727
    case 0xaf:
2728
        if ((b & 1) == 0)
2729
            ot = OT_BYTE;
2730
        else
2731
                ot = dflag ? OT_LONG : OT_WORD;
2732
        if (prefixes & PREFIX_REPNZ) {
2733
            if (s->cc_op != CC_OP_DYNAMIC)
2734
                gen_op_set_cc_op(s->cc_op);
2735
            gen_string_es(s, ot, gen_op_scas + 9 * 2);
2736
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2737
        } else if (prefixes & PREFIX_REPZ) {
2738
            if (s->cc_op != CC_OP_DYNAMIC)
2739
                gen_op_set_cc_op(s->cc_op);
2740
            gen_string_es(s, ot, gen_op_scas + 9);
2741
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2742
        } else {
2743
            gen_string_es(s, ot, gen_op_scas);
2744
            s->cc_op = CC_OP_SUBB + ot;
2745
        }
2746
        break;
2747

    
2748
    case 0xa6: /* cmpsS */
2749
    case 0xa7:
2750
        if ((b & 1) == 0)
2751
            ot = OT_BYTE;
2752
        else
2753
            ot = dflag ? OT_LONG : OT_WORD;
2754
        if (prefixes & PREFIX_REPNZ) {
2755
            if (s->cc_op != CC_OP_DYNAMIC)
2756
                gen_op_set_cc_op(s->cc_op);
2757
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2758
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2759
        } else if (prefixes & PREFIX_REPZ) {
2760
            if (s->cc_op != CC_OP_DYNAMIC)
2761
                gen_op_set_cc_op(s->cc_op);
2762
            gen_string_ds(s, ot, gen_op_cmps + 9);
2763
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2764
        } else {
2765
            gen_string_ds(s, ot, gen_op_cmps);
2766
            s->cc_op = CC_OP_SUBB + ot;
2767
        }
2768
        break;
2769
    case 0x6c: /* insS */
2770
    case 0x6d:
2771
        if (s->cpl > s->iopl || s->vm86) {
2772
            /* NOTE: even for (E)CX = 0 the exception is raised */
2773
            gen_op_gpf(pc_start - s->cs_base);
2774
        } else {
2775
            if ((b & 1) == 0)
2776
                ot = OT_BYTE;
2777
            else
2778
                ot = dflag ? OT_LONG : OT_WORD;
2779
            if (prefixes & PREFIX_REPZ) {
2780
                gen_string_es(s, ot, gen_op_ins + 9);
2781
            } else {
2782
                gen_string_es(s, ot, gen_op_ins);
2783
            }
2784
        }
2785
        break;
2786
    case 0x6e: /* outsS */
2787
    case 0x6f:
2788
        if (s->cpl > s->iopl || s->vm86) {
2789
            /* NOTE: even for (E)CX = 0 the exception is raised */
2790
            gen_op_gpf(pc_start - s->cs_base);
2791
        } else {
2792
            if ((b & 1) == 0)
2793
                ot = OT_BYTE;
2794
            else
2795
                ot = dflag ? OT_LONG : OT_WORD;
2796
            if (prefixes & PREFIX_REPZ) {
2797
                gen_string_ds(s, ot, gen_op_outs + 9);
2798
            } else {
2799
                gen_string_ds(s, ot, gen_op_outs);
2800
            }
2801
        }
2802
        break;
2803

    
2804
        /************************/
2805
        /* port I/O */
2806
    case 0xe4:
2807
    case 0xe5:
2808
        if (s->cpl > s->iopl || s->vm86) {
2809
            gen_op_gpf(pc_start - s->cs_base);
2810
        } else {
2811
            if ((b & 1) == 0)
2812
                ot = OT_BYTE;
2813
            else
2814
                ot = dflag ? OT_LONG : OT_WORD;
2815
            val = ldub(s->pc++);
2816
            gen_op_movl_T0_im(val);
2817
            gen_op_in[ot]();
2818
            gen_op_mov_reg_T1[ot][R_EAX]();
2819
        }
2820
        break;
2821
    case 0xe6:
2822
    case 0xe7:
2823
        if (s->cpl > s->iopl || s->vm86) {
2824
            gen_op_gpf(pc_start - s->cs_base);
2825
        } else {
2826
            if ((b & 1) == 0)
2827
                ot = OT_BYTE;
2828
            else
2829
                ot = dflag ? OT_LONG : OT_WORD;
2830
            val = ldub(s->pc++);
2831
            gen_op_movl_T0_im(val);
2832
            gen_op_mov_TN_reg[ot][1][R_EAX]();
2833
            gen_op_out[ot]();
2834
        }
2835
        break;
2836
    case 0xec:
2837
    case 0xed:
2838
        if (s->cpl > s->iopl || s->vm86) {
2839
            gen_op_gpf(pc_start - s->cs_base);
2840
        } else {
2841
            if ((b & 1) == 0)
2842
                ot = OT_BYTE;
2843
            else
2844
                ot = dflag ? OT_LONG : OT_WORD;
2845
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2846
            gen_op_in[ot]();
2847
            gen_op_mov_reg_T1[ot][R_EAX]();
2848
        }
2849
        break;
2850
    case 0xee:
2851
    case 0xef:
2852
        if (s->cpl > s->iopl || s->vm86) {
2853
            gen_op_gpf(pc_start - s->cs_base);
2854
        } else {
2855
            if ((b & 1) == 0)
2856
                ot = OT_BYTE;
2857
            else
2858
                ot = dflag ? OT_LONG : OT_WORD;
2859
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2860
            gen_op_mov_TN_reg[ot][1][R_EAX]();
2861
            gen_op_out[ot]();
2862
        }
2863
        break;
2864

    
2865
        /************************/
2866
        /* control */
2867
    case 0xc2: /* ret im */
2868
        val = ldsw(s->pc);
2869
        s->pc += 2;
2870
        gen_pop_T0(s);
2871
        if (s->ss32)
2872
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2873
        else
2874
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2875
        if (s->dflag == 0)
2876
            gen_op_andl_T0_ffff();
2877
        gen_op_jmp_T0();
2878
        s->is_jmp = 1;
2879
        break;
2880
    case 0xc3: /* ret */
2881
        gen_pop_T0(s);
2882
        gen_pop_update(s);
2883
        if (s->dflag == 0)
2884
            gen_op_andl_T0_ffff();
2885
        gen_op_jmp_T0();
2886
        s->is_jmp = 1;
2887
        break;
2888
    case 0xca: /* lret im */
2889
        /* XXX: not restartable */
2890
        val = ldsw(s->pc);
2891
        s->pc += 2;
2892
        /* pop offset */
2893
        gen_pop_T0(s);
2894
        if (s->dflag == 0)
2895
            gen_op_andl_T0_ffff();
2896
        gen_op_jmp_T0();
2897
        gen_pop_update(s);
2898
        /* pop selector */
2899
        gen_pop_T0(s);
2900
        gen_movl_seg_T0(s, R_CS);
2901
        gen_pop_update(s);
2902
        /* add stack offset */
2903
        if (s->ss32)
2904
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2905
        else
2906
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2907
        s->is_jmp = 1;
2908
        break;
2909
    case 0xcb: /* lret */
2910
        /* XXX: not restartable */
2911
        /* pop offset */
2912
        gen_pop_T0(s);
2913
        if (s->dflag == 0)
2914
            gen_op_andl_T0_ffff();
2915
        gen_op_jmp_T0();
2916
        gen_pop_update(s);
2917
        /* pop selector */
2918
        gen_pop_T0(s);
2919
        gen_movl_seg_T0(s, R_CS);
2920
        gen_pop_update(s);
2921
        s->is_jmp = 1;
2922
        break;
2923
    case 0xcf: /* iret */
2924
        /* XXX: not restartable */
2925
        /* pop offset */
2926
        gen_pop_T0(s);
2927
        if (s->dflag == 0)
2928
            gen_op_andl_T0_ffff();
2929
        gen_op_jmp_T0();
2930
        gen_pop_update(s);
2931
        /* pop selector */
2932
        gen_pop_T0(s);
2933
        gen_movl_seg_T0(s, R_CS);
2934
        gen_pop_update(s);
2935
        /* pop eflags */
2936
        gen_pop_T0(s);
2937
        if (s->dflag) {
2938
            if (s->vm86)
2939
                gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
2940
            else
2941
                gen_op_movl_eflags_T0();
2942
        } else {
2943
            if (s->vm86)
2944
                gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
2945
            else
2946
                gen_op_movw_eflags_T0();
2947
        }
2948
        gen_pop_update(s);
2949
        s->cc_op = CC_OP_EFLAGS;
2950
        s->is_jmp = 1;
2951
        break;
2952
    case 0xe8: /* call im */
2953
        {
2954
            unsigned int next_eip;
2955
            ot = dflag ? OT_LONG : OT_WORD;
2956
            val = insn_get(s, ot);
2957
            next_eip = s->pc - s->cs_base;
2958
            val += next_eip;
2959
            if (s->dflag == 0)
2960
                val &= 0xffff;
2961
            gen_op_movl_T0_im(next_eip);
2962
            gen_push_T0(s);
2963
            gen_op_jmp_im(val);
2964
            s->is_jmp = 1;
2965
        }
2966
        break;
2967
    case 0x9a: /* lcall im */
2968
        {
2969
            unsigned int selector, offset;
2970

    
2971
            ot = dflag ? OT_LONG : OT_WORD;
2972
            offset = insn_get(s, ot);
2973
            selector = insn_get(s, OT_WORD);
2974
            
2975
            /* push return segment + offset */
2976
            gen_op_movl_T0_seg(R_CS);
2977
            gen_push_T0(s);
2978
            next_eip = s->pc - s->cs_base;
2979
            gen_op_movl_T0_im(next_eip);
2980
            gen_push_T0(s);
2981

    
2982
            /* change cs and pc */
2983
            gen_op_movl_T0_im(selector);
2984
            gen_movl_seg_T0(s, R_CS);
2985
            gen_op_jmp_im((unsigned long)offset);
2986
            s->is_jmp = 1;
2987
        }
2988
        break;
2989
    case 0xe9: /* jmp */
2990
        ot = dflag ? OT_LONG : OT_WORD;
2991
        val = insn_get(s, ot);
2992
        val += s->pc - s->cs_base;
2993
        if (s->dflag == 0)
2994
            val = val & 0xffff;
2995
        gen_op_jmp_im(val);
2996
        s->is_jmp = 1;
2997
        break;
2998
    case 0xea: /* ljmp im */
2999
        {
3000
            unsigned int selector, offset;
3001

    
3002
            ot = dflag ? OT_LONG : OT_WORD;
3003
            offset = insn_get(s, ot);
3004
            selector = insn_get(s, OT_WORD);
3005
            
3006
            /* change cs and pc */
3007
            gen_op_movl_T0_im(selector);
3008
            gen_movl_seg_T0(s, R_CS);
3009
            gen_op_jmp_im((unsigned long)offset);
3010
            s->is_jmp = 1;
3011
        }
3012
        break;
3013
    case 0xeb: /* jmp Jb */
3014
        val = (int8_t)insn_get(s, OT_BYTE);
3015
        val += s->pc - s->cs_base;
3016
        if (s->dflag == 0)
3017
            val = val & 0xffff;
3018
        gen_op_jmp_im(val);
3019
        s->is_jmp = 1;
3020
        break;
3021
    case 0x70 ... 0x7f: /* jcc Jb */
3022
        val = (int8_t)insn_get(s, OT_BYTE);
3023
        goto do_jcc;
3024
    case 0x180 ... 0x18f: /* jcc Jv */
3025
        if (dflag) {
3026
            val = insn_get(s, OT_LONG);
3027
        } else {
3028
            val = (int16_t)insn_get(s, OT_WORD); 
3029
        }
3030
    do_jcc:
3031
        next_eip = s->pc - s->cs_base;
3032
        val += next_eip;
3033
        if (s->dflag == 0)
3034
            val &= 0xffff;
3035
        gen_jcc(s, b, val, next_eip);
3036
        s->is_jmp = 1;
3037
        break;
3038

    
3039
    case 0x190 ... 0x19f: /* setcc Gv */
3040
        modrm = ldub(s->pc++);
3041
        gen_setcc(s, b);
3042
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3043
        break;
3044
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3045
        ot = dflag ? OT_LONG : OT_WORD;
3046
        modrm = ldub(s->pc++);
3047
        reg = (modrm >> 3) & 7;
3048
        mod = (modrm >> 6) & 3;
3049
        gen_setcc(s, b);
3050
        if (mod != 3) {
3051
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3052
            gen_op_ld_T1_A0[ot]();
3053
        } else {
3054
            rm = modrm & 7;
3055
            gen_op_mov_TN_reg[ot][1][rm]();
3056
        }
3057
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3058
        break;
3059
        
3060
        /************************/
3061
        /* flags */
3062
    case 0x9c: /* pushf */
3063
        if (s->cc_op != CC_OP_DYNAMIC)
3064
            gen_op_set_cc_op(s->cc_op);
3065
        if (s->vm86)
3066
            gen_op_movl_T0_eflags_vm();
3067
        else
3068
            gen_op_movl_T0_eflags();
3069
        gen_push_T0(s);
3070
        break;
3071
    case 0x9d: /* popf */
3072
        gen_pop_T0(s);
3073
        if (s->dflag) {
3074
            if (s->vm86)
3075
                gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
3076
            else
3077
                gen_op_movl_eflags_T0();
3078
        } else {
3079
            if (s->vm86)
3080
                gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
3081
            else
3082
                gen_op_movw_eflags_T0();
3083
        }
3084
        gen_pop_update(s);
3085
        s->cc_op = CC_OP_EFLAGS;
3086
        break;
3087
    case 0x9e: /* sahf */
3088
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3089
        if (s->cc_op != CC_OP_DYNAMIC)
3090
            gen_op_set_cc_op(s->cc_op);
3091
        gen_op_movb_eflags_T0();
3092
        s->cc_op = CC_OP_EFLAGS;
3093
        break;
3094
    case 0x9f: /* lahf */
3095
        if (s->cc_op != CC_OP_DYNAMIC)
3096
            gen_op_set_cc_op(s->cc_op);
3097
        gen_op_movl_T0_eflags();
3098
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3099
        break;
3100
    case 0xf5: /* cmc */
3101
        if (s->cc_op != CC_OP_DYNAMIC)
3102
            gen_op_set_cc_op(s->cc_op);
3103
        gen_op_cmc();
3104
        s->cc_op = CC_OP_EFLAGS;
3105
        break;
3106
    case 0xf8: /* clc */
3107
        if (s->cc_op != CC_OP_DYNAMIC)
3108
            gen_op_set_cc_op(s->cc_op);
3109
        gen_op_clc();
3110
        s->cc_op = CC_OP_EFLAGS;
3111
        break;
3112
    case 0xf9: /* stc */
3113
        if (s->cc_op != CC_OP_DYNAMIC)
3114
            gen_op_set_cc_op(s->cc_op);
3115
        gen_op_stc();
3116
        s->cc_op = CC_OP_EFLAGS;
3117
        break;
3118
    case 0xfc: /* cld */
3119
        gen_op_cld();
3120
        break;
3121
    case 0xfd: /* std */
3122
        gen_op_std();
3123
        break;
3124

    
3125
        /************************/
3126
        /* bit operations */
3127
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
3128
        ot = dflag ? OT_LONG : OT_WORD;
3129
        modrm = ldub(s->pc++);
3130
        op = (modrm >> 3) & 7;
3131
        mod = (modrm >> 6) & 3;
3132
        rm = modrm & 7;
3133
        if (mod != 3) {
3134
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3135
            gen_op_ld_T0_A0[ot]();
3136
        } else {
3137
            gen_op_mov_TN_reg[ot][0][rm]();
3138
        }
3139
        /* load shift */
3140
        val = ldub(s->pc++);
3141
        gen_op_movl_T1_im(val);
3142
        if (op < 4)
3143
            goto illegal_op;
3144
        op -= 4;
3145
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3146
        s->cc_op = CC_OP_SARB + ot;
3147
        if (op != 0) {
3148
            if (mod != 3)
3149
                gen_op_st_T0_A0[ot]();
3150
            else
3151
                gen_op_mov_reg_T0[ot][rm]();
3152
        }
3153
        break;
3154
    case 0x1a3: /* bt Gv, Ev */
3155
        op = 0;
3156
        goto do_btx;
3157
    case 0x1ab: /* bts */
3158
        op = 1;
3159
        goto do_btx;
3160
    case 0x1b3: /* btr */
3161
        op = 2;
3162
        goto do_btx;
3163
    case 0x1bb: /* btc */
3164
        op = 3;
3165
    do_btx:
3166
        ot = dflag ? OT_LONG : OT_WORD;
3167
        modrm = ldub(s->pc++);
3168
        reg = (modrm >> 3) & 7;
3169
        mod = (modrm >> 6) & 3;
3170
        rm = modrm & 7;
3171
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3172
        if (mod != 3) {
3173
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3174
            /* specific case: we need to add a displacement */
3175
            if (ot == OT_WORD)
3176
                gen_op_add_bitw_A0_T1();
3177
            else
3178
                gen_op_add_bitl_A0_T1();
3179
            gen_op_ld_T0_A0[ot]();
3180
        } else {
3181
            gen_op_mov_TN_reg[ot][0][rm]();
3182
        }
3183
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3184
        s->cc_op = CC_OP_SARB + ot;
3185
        if (op != 0) {
3186
            if (mod != 3)
3187
                gen_op_st_T0_A0[ot]();
3188
            else
3189
                gen_op_mov_reg_T0[ot][rm]();
3190
        }
3191
        break;
3192
    case 0x1bc: /* bsf */
3193
    case 0x1bd: /* bsr */
3194
        ot = dflag ? OT_LONG : OT_WORD;
3195
        modrm = ldub(s->pc++);
3196
        reg = (modrm >> 3) & 7;
3197
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3198
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3199
        /* NOTE: we always write back the result. Intel doc says it is
3200
           undefined if T0 == 0 */
3201
        gen_op_mov_reg_T0[ot][reg]();
3202
        s->cc_op = CC_OP_LOGICB + ot;
3203
        break;
3204
        /************************/
3205
        /* bcd */
3206
    case 0x27: /* daa */
3207
        if (s->cc_op != CC_OP_DYNAMIC)
3208
            gen_op_set_cc_op(s->cc_op);
3209
        gen_op_daa();
3210
        s->cc_op = CC_OP_EFLAGS;
3211
        break;
3212
    case 0x2f: /* das */
3213
        if (s->cc_op != CC_OP_DYNAMIC)
3214
            gen_op_set_cc_op(s->cc_op);
3215
        gen_op_das();
3216
        s->cc_op = CC_OP_EFLAGS;
3217
        break;
3218
    case 0x37: /* aaa */
3219
        if (s->cc_op != CC_OP_DYNAMIC)
3220
            gen_op_set_cc_op(s->cc_op);
3221
        gen_op_aaa();
3222
        s->cc_op = CC_OP_EFLAGS;
3223
        break;
3224
    case 0x3f: /* aas */
3225
        if (s->cc_op != CC_OP_DYNAMIC)
3226
            gen_op_set_cc_op(s->cc_op);
3227
        gen_op_aas();
3228
        s->cc_op = CC_OP_EFLAGS;
3229
        break;
3230
    case 0xd4: /* aam */
3231
        val = ldub(s->pc++);
3232
        gen_op_aam(val);
3233
        s->cc_op = CC_OP_LOGICB;
3234
        break;
3235
    case 0xd5: /* aad */
3236
        val = ldub(s->pc++);
3237
        gen_op_aad(val);
3238
        s->cc_op = CC_OP_LOGICB;
3239
        break;
3240
        /************************/
3241
        /* misc */
3242
    case 0x90: /* nop */
3243
        break;
3244
    case 0xcc: /* int3 */
3245
        gen_op_int3((long)pc_start);
3246
        s->is_jmp = 1;
3247
        break;
3248
    case 0xcd: /* int N */
3249
        val = ldub(s->pc++);
3250
        gen_op_int_im(val, pc_start - s->cs_base);
3251
        s->is_jmp = 1;
3252
        break;
3253
    case 0xce: /* into */
3254
        if (s->cc_op != CC_OP_DYNAMIC)
3255
            gen_op_set_cc_op(s->cc_op);
3256
        gen_op_into();
3257
        break;
3258
    case 0xfa: /* cli */
3259
        if (!s->vm86) {
3260
            if (s->cpl <= s->iopl)
3261
                gen_op_cli();
3262
            else
3263
                gen_op_gpf(pc_start - s->cs_base);
3264
        } else {
3265
            if (s->iopl == 3)
3266
                gen_op_cli();
3267
            else
3268
                gen_op_cli_vm();
3269
        }
3270
        break;
3271
    case 0xfb: /* sti */
3272
        if (!s->vm86) {
3273
            if (s->cpl <= s->iopl)
3274
                gen_op_sti();
3275
            else
3276
                gen_op_gpf(pc_start - s->cs_base);
3277
        } else {
3278
            if (s->iopl == 3)
3279
                gen_op_sti();
3280
            else
3281
                gen_op_sti_vm(pc_start - s->cs_base);
3282
        }
3283
        break;
3284
    case 0x62: /* bound */
3285
        ot = dflag ? OT_LONG : OT_WORD;
3286
        modrm = ldub(s->pc++);
3287
        reg = (modrm >> 3) & 7;
3288
        mod = (modrm >> 6) & 3;
3289
        if (mod == 3)
3290
            goto illegal_op;
3291
        gen_op_mov_reg_T0[ot][reg]();
3292
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3293
        if (ot == OT_WORD)
3294
            gen_op_boundw();
3295
        else
3296
            gen_op_boundl();
3297
        break;
3298
    case 0x1c8 ... 0x1cf: /* bswap reg */
3299
        reg = b & 7;
3300
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3301
        gen_op_bswapl_T0();
3302
        gen_op_mov_reg_T0[OT_LONG][reg]();
3303
        break;
3304
    case 0xd6: /* salc */
3305
        if (s->cc_op != CC_OP_DYNAMIC)
3306
            gen_op_set_cc_op(s->cc_op);
3307
        gen_op_salc();
3308
        break;
3309
    case 0xe0: /* loopnz */
3310
    case 0xe1: /* loopz */
3311
        if (s->cc_op != CC_OP_DYNAMIC)
3312
            gen_op_set_cc_op(s->cc_op);
3313
        /* FALL THRU */
3314
    case 0xe2: /* loop */
3315
    case 0xe3: /* jecxz */
3316
        val = (int8_t)insn_get(s, OT_BYTE);
3317
        next_eip = s->pc - s->cs_base;
3318
        val += next_eip;
3319
        if (s->dflag == 0)
3320
            val &= 0xffff;
3321
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3322
        s->is_jmp = 1;
3323
        break;
3324
    case 0x131: /* rdtsc */
3325
        gen_op_rdtsc();
3326
        break;
3327
    case 0x1a2: /* cpuid */
3328
        gen_op_cpuid();
3329
        break;
3330
    case 0xf4: /* hlt */
3331
        if (s->cpl == 0) {
3332
            /* ignored */
3333
        } else {
3334
            gen_op_gpf(pc_start - s->cs_base);
3335
        }
3336
        break;
3337
    default:
3338
        goto illegal_op;
3339
    }
3340
    /* lock generation */
3341
    if (s->prefix & PREFIX_LOCK)
3342
        gen_op_unlock();
3343
    return (long)s->pc;
3344
 illegal_op:
3345
    /* XXX: ensure that no lock was generated */
3346
    return -1;
3347
}
3348

    
3349
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3350
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3351

    
3352
/* flags read by an operation */
3353
static uint16_t opc_read_flags[NB_OPS] = { 
3354
    [INDEX_op_aas] = CC_A,
3355
    [INDEX_op_aaa] = CC_A,
3356
    [INDEX_op_das] = CC_A | CC_C,
3357
    [INDEX_op_daa] = CC_A | CC_C,
3358

    
3359
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3360
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3361
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3362
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3363
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3364
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3365

    
3366
    /* subtle: due to the incl/decl implementation, C is used */
3367
    [INDEX_op_incl_T0_cc] = CC_C, 
3368
    [INDEX_op_decl_T0_cc] = CC_C,
3369

    
3370
    [INDEX_op_into] = CC_O,
3371

    
3372
    [INDEX_op_jo_cc] = CC_O,
3373
    [INDEX_op_jb_cc] = CC_C,
3374
    [INDEX_op_jz_cc] = CC_Z,
3375
    [INDEX_op_jbe_cc] = CC_Z | CC_C,
3376
    [INDEX_op_js_cc] = CC_S,
3377
    [INDEX_op_jp_cc] = CC_P,
3378
    [INDEX_op_jl_cc] = CC_O | CC_S,
3379
    [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3380

    
3381
    [INDEX_op_jb_subb] = CC_C,
3382
    [INDEX_op_jb_subw] = CC_C,
3383
    [INDEX_op_jb_subl] = CC_C,
3384

    
3385
    [INDEX_op_jz_subb] = CC_Z,
3386
    [INDEX_op_jz_subw] = CC_Z,
3387
    [INDEX_op_jz_subl] = CC_Z,
3388

    
3389
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3390
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3391
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3392

    
3393
    [INDEX_op_js_subb] = CC_S,
3394
    [INDEX_op_js_subw] = CC_S,
3395
    [INDEX_op_js_subl] = CC_S,
3396

    
3397
    [INDEX_op_jl_subb] = CC_O | CC_S,
3398
    [INDEX_op_jl_subw] = CC_O | CC_S,
3399
    [INDEX_op_jl_subl] = CC_O | CC_S,
3400

    
3401
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3402
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3403
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3404

    
3405
    [INDEX_op_loopnzw] = CC_Z,
3406
    [INDEX_op_loopnzl] = CC_Z,
3407
    [INDEX_op_loopzw] = CC_Z,
3408
    [INDEX_op_loopzl] = CC_Z,
3409

    
3410
    [INDEX_op_seto_T0_cc] = CC_O,
3411
    [INDEX_op_setb_T0_cc] = CC_C,
3412
    [INDEX_op_setz_T0_cc] = CC_Z,
3413
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3414
    [INDEX_op_sets_T0_cc] = CC_S,
3415
    [INDEX_op_setp_T0_cc] = CC_P,
3416
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3417
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3418

    
3419
    [INDEX_op_setb_T0_subb] = CC_C,
3420
    [INDEX_op_setb_T0_subw] = CC_C,
3421
    [INDEX_op_setb_T0_subl] = CC_C,
3422

    
3423
    [INDEX_op_setz_T0_subb] = CC_Z,
3424
    [INDEX_op_setz_T0_subw] = CC_Z,
3425
    [INDEX_op_setz_T0_subl] = CC_Z,
3426

    
3427
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3428
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3429
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3430

    
3431
    [INDEX_op_sets_T0_subb] = CC_S,
3432
    [INDEX_op_sets_T0_subw] = CC_S,
3433
    [INDEX_op_sets_T0_subl] = CC_S,
3434

    
3435
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3436
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3437
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3438

    
3439
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3440
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3441
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3442

    
3443
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3444
    [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
3445
    [INDEX_op_cmc] = CC_C,
3446
    [INDEX_op_salc] = CC_C,
3447

    
3448
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3449
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3450
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3451
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3452
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3453
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3454
};
3455

    
3456
/* flags written by an operation */
3457
static uint16_t opc_write_flags[NB_OPS] = { 
3458
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3459
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3460
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3461
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3462
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3463
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3464
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3465
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3466
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3467
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3468
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3469
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3470
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3471
    /* subtle: due to the incl/decl implementation, C is used */
3472
    [INDEX_op_incl_T0_cc] = CC_OSZAPC, 
3473
    [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3474
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3475

    
3476
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3477
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3478
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3479
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3480
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3481
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3482
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3483
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3484
    
3485
    /* bcd */
3486
    [INDEX_op_aam] = CC_OSZAPC,
3487
    [INDEX_op_aad] = CC_OSZAPC,
3488
    [INDEX_op_aas] = CC_OSZAPC,
3489
    [INDEX_op_aaa] = CC_OSZAPC,
3490
    [INDEX_op_das] = CC_OSZAPC,
3491
    [INDEX_op_daa] = CC_OSZAPC,
3492

    
3493
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3494
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3495
    [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC,
3496
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3497
    [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC,
3498
    [INDEX_op_clc] = CC_C,
3499
    [INDEX_op_stc] = CC_C,
3500
    [INDEX_op_cmc] = CC_C,
3501

    
3502
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3503
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3504
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3505
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3506
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3507
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3508

    
3509
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3510
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3511
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3512
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3513
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3514
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3515

    
3516
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3517
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3518
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3519

    
3520
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3521
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3522
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3523

    
3524
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3525
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3526
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3527

    
3528
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3529
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3530
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3531
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3532

    
3533
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3534
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3535
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3536
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3537

    
3538
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3539
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3540
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3541
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3542
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3543
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3544
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3545
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3546

    
3547
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3548
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3549
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3550
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3551

    
3552
#undef STRINGOP
3553
#define STRINGOP(x) \
3554
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3555
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3556
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3557
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3558
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3559
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3560
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3561
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3562
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3563

    
3564
    STRINGOP(scas)
3565
    STRINGOP(repz_scas)
3566
    STRINGOP(repnz_scas)
3567
    STRINGOP(cmps)
3568
    STRINGOP(repz_cmps)
3569
    STRINGOP(repnz_cmps)
3570

    
3571
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3572
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3573
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3574

    
3575
    [INDEX_op_cmpxchg8b] = CC_Z,
3576
};
3577

    
3578
/* simpler form of an operation if no flags need to be generated */
3579
static uint16_t opc_simpler[NB_OPS] = { 
3580
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3581
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3582
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3583
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3584
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3585
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3586
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3587
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3588

    
3589
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3590
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3591
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3592

    
3593
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3594
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3595
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3596

    
3597
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3598
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3599
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3600

    
3601
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3602
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3603
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3604

    
3605
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3606
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3607
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3608
};
3609

    
3610
static void optimize_flags_init(void)
3611
{
3612
    int i;
3613
    /* put default values in arrays */
3614
    for(i = 0; i < NB_OPS; i++) {
3615
        if (opc_simpler[i] == 0)
3616
            opc_simpler[i] = i;
3617
    }
3618
}
3619

    
3620
/* CPU flags computation optimization: we move backward thru the
3621
   generated code to see which flags are needed. The operation is
3622
   modified if suitable */
3623
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3624
{
3625
    uint16_t *opc_ptr;
3626
    int live_flags, write_flags, op;
3627

    
3628
    opc_ptr = opc_buf + opc_buf_len;
3629
    /* live_flags contains the flags needed by the next instructions
3630
       in the code. At the end of the bloc, we consider that all the
3631
       flags are live. */
3632
    live_flags = CC_OSZAPC;
3633
    while (opc_ptr > opc_buf) {
3634
        op = *--opc_ptr;
3635
        /* if none of the flags written by the instruction is used,
3636
           then we can try to find a simpler instruction */
3637
        write_flags = opc_write_flags[op];
3638
        if ((live_flags & write_flags) == 0) {
3639
            *opc_ptr = opc_simpler[op];
3640
        }
3641
        /* compute the live flags before the instruction */
3642
        live_flags &= ~write_flags;
3643
        live_flags |= opc_read_flags[op];
3644
    }
3645
}
3646

    
3647

    
3648
#ifdef DEBUG_DISAS
3649
static const char *op_str[] = {
3650
#define DEF(s, n) #s,
3651
#include "opc-i386.h"
3652
#undef DEF
3653
};
3654

    
3655
static uint8_t op_nb_args[] = {
3656
#define DEF(s, n) n,
3657
#include "opc-i386.h"
3658
#undef DEF
3659
};
3660

    
3661
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3662
{
3663
    const uint16_t *opc_ptr;
3664
    const uint32_t *opparam_ptr;
3665
    int c, n, i;
3666

    
3667
    opc_ptr = opc_buf;
3668
    opparam_ptr = opparam_buf;
3669
    for(;;) {
3670
        c = *opc_ptr++;
3671
        n = op_nb_args[c];
3672
        fprintf(logfile, "0x%04x: %s", opc_ptr - opc_buf - 1, op_str[c]);
3673
        for(i = 0; i < n; i++) {
3674
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
3675
        }
3676
        fprintf(logfile, "\n");
3677
        if (c == INDEX_op_end)
3678
            break;
3679
        opparam_ptr += n;
3680
    }
3681
}
3682

    
3683
#endif
3684

    
3685
/* XXX: make this buffer thread safe */
3686
/* XXX: make safe guess about sizes */
3687
#define MAX_OP_PER_INSTR 32
3688
#define OPC_BUF_SIZE 512
3689
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3690

    
3691
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3692

    
3693
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3694
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3695

    
3696
/* return non zero if the very first instruction is invalid so that
3697
   the virtual CPU can trigger an exception. */
3698
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3699
                     int *gen_code_size_ptr,
3700
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3701
{
3702
    DisasContext dc1, *dc = &dc1;
3703
    uint8_t *pc_ptr;
3704
    uint16_t *gen_opc_end;
3705
    int gen_code_size;
3706
    long ret;
3707
    
3708
    /* generate intermediate code */
3709

    
3710
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3711
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3712
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3713
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3714
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3715
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3716
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3717
    dc->cc_op = CC_OP_DYNAMIC;
3718
    dc->cs_base = cs_base;
3719

    
3720
    gen_opc_ptr = gen_opc_buf;
3721
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3722
    gen_opparam_ptr = gen_opparam_buf;
3723

    
3724
    dc->is_jmp = 0;
3725
    pc_ptr = pc_start;
3726
    do {
3727
        ret = disas_insn(dc, pc_ptr);
3728
        if (ret == -1) {
3729
            /* we trigger an illegal instruction operation only if it
3730
               is the first instruction. Otherwise, we simply stop
3731
               generating the code just before it */
3732
            if (pc_ptr == pc_start)
3733
                return -1;
3734
            else
3735
                break;
3736
        }
3737
        pc_ptr = (void *)ret;
3738
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3739
    /* we must store the eflags state if it is not already done */
3740
    if (dc->cc_op != CC_OP_DYNAMIC)
3741
        gen_op_set_cc_op(dc->cc_op);
3742
    if (dc->is_jmp != 1) {
3743
        /* we add an additionnal jmp to update the simulated PC */
3744
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3745
    }
3746
    *gen_opc_ptr = INDEX_op_end;
3747

    
3748
#ifdef DEBUG_DISAS
3749
    if (loglevel) {
3750
        fprintf(logfile, "----------------\n");
3751
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3752
        disas(logfile, pc_start, pc_ptr - pc_start,
3753
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3754
        fprintf(logfile, "\n");
3755

    
3756
        fprintf(logfile, "OP:\n");
3757
        dump_ops(gen_opc_buf, gen_opparam_buf);
3758
        fprintf(logfile, "\n");
3759
    }
3760
#endif
3761

    
3762
    /* optimize flag computations */
3763
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3764

    
3765
#ifdef DEBUG_DISAS
3766
    if (loglevel) {
3767
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3768
        dump_ops(gen_opc_buf, gen_opparam_buf);
3769
        fprintf(logfile, "\n");
3770
    }
3771
#endif
3772

    
3773
    /* generate machine code */
3774
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3775
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3776
    *gen_code_size_ptr = gen_code_size;
3777

    
3778
#ifdef DEBUG_DISAS
3779
    if (loglevel) {
3780
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3781
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3782
        fprintf(logfile, "\n");
3783
        fflush(logfile);
3784
    }
3785
#endif
3786
    return 0;
3787
}
3788

    
3789
CPUX86State *cpu_x86_init(void)
3790
{
3791
    CPUX86State *env;
3792
    int i;
3793
    static int inited;
3794

    
3795
    cpu_x86_tblocks_init();
3796

    
3797
    env = malloc(sizeof(CPUX86State));
3798
    if (!env)
3799
        return NULL;
3800
    memset(env, 0, sizeof(CPUX86State));
3801
    /* basic FPU init */
3802
    for(i = 0;i < 8; i++)
3803
        env->fptags[i] = 1;
3804
    env->fpuc = 0x37f;
3805
    /* flags setup : we activate the IRQs by default as in user mode */
3806
    env->eflags = 0x2 | IF_MASK;
3807

    
3808
    /* init various static tables */
3809
    if (!inited) {
3810
        inited = 1;
3811
        optimize_flags_init();
3812
    }
3813
    return env;
3814
}
3815

    
3816
void cpu_x86_close(CPUX86State *env)
3817
{
3818
    free(env);
3819
}