Statistics
| Branch: | Revision:

root / translate-i386.c @ 504e56eb

History | View | Annotate | Download (100.5 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
} DisasContext;
134

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

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

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

    
166
#include "op-i386.h"
167

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
586
/* the _a32 and _a16 string operations use A0 as the base register. */
587

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

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

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

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

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

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

    
631

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

    
637

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

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

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

    
679

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

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

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

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

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

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

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

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

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

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

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

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

    
880
    gen_op_shift_T0_T1_cc[ot][op]();
881

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

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

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

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

    
910
    if (s->aflag) {
911

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

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

    
1032
    opreg = OR_A0;
1033
    disp = 0;
1034
    *reg_ptr = opreg;
1035
    *offset_ptr = disp;
1036
}
1037

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1430
    s->prefix = prefixes;
1431
    s->aflag = aflag;
1432
    s->dflag = dflag;
1433

    
1434
    /* lock generation */
1435
    if (prefixes & PREFIX_LOCK)
1436
        gen_op_lock();
1437

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2746
    case 0xa6: /* cmpsS */
2747
    case 0xa7:
2748
        if ((b & 1) == 0)
2749
            ot = OT_BYTE;
2750
        else
2751
            ot = dflag ? OT_LONG : OT_WORD;
2752
        if (prefixes & PREFIX_REPNZ) {
2753
            if (s->cc_op != CC_OP_DYNAMIC)
2754
                gen_op_set_cc_op(s->cc_op);
2755
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2756
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2757
        } else if (prefixes & PREFIX_REPZ) {
2758
            if (s->cc_op != CC_OP_DYNAMIC)
2759
                gen_op_set_cc_op(s->cc_op);
2760
            gen_string_ds(s, ot, gen_op_cmps + 9);
2761
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2762
        } else {
2763
            gen_string_ds(s, ot, gen_op_cmps);
2764
            s->cc_op = CC_OP_SUBB + ot;
2765
        }
2766
        break;
2767
    case 0x6c: /* insS */
2768
    case 0x6d:
2769
        if ((b & 1) == 0)
2770
            ot = OT_BYTE;
2771
        else
2772
            ot = dflag ? OT_LONG : OT_WORD;
2773
        if (prefixes & PREFIX_REPZ) {
2774
            gen_string_es(s, ot, gen_op_ins + 9);
2775
        } else {
2776
            gen_string_es(s, ot, gen_op_ins);
2777
        }
2778
        break;
2779
    case 0x6e: /* outsS */
2780
    case 0x6f:
2781
        if ((b & 1) == 0)
2782
            ot = OT_BYTE;
2783
        else
2784
            ot = dflag ? OT_LONG : OT_WORD;
2785
        if (prefixes & PREFIX_REPZ) {
2786
            gen_string_ds(s, ot, gen_op_outs + 9);
2787
        } else {
2788
            gen_string_ds(s, ot, gen_op_outs);
2789
        }
2790
        break;
2791

    
2792
        /************************/
2793
        /* port I/O */
2794
    case 0xe4:
2795
    case 0xe5:
2796
        if ((b & 1) == 0)
2797
            ot = OT_BYTE;
2798
        else
2799
            ot = dflag ? OT_LONG : OT_WORD;
2800
        val = ldub(s->pc++);
2801
        gen_op_movl_T0_im(val);
2802
        gen_op_in[ot]();
2803
        gen_op_mov_reg_T1[ot][R_EAX]();
2804
        break;
2805
    case 0xe6:
2806
    case 0xe7:
2807
        if ((b & 1) == 0)
2808
            ot = OT_BYTE;
2809
        else
2810
            ot = dflag ? OT_LONG : OT_WORD;
2811
        val = ldub(s->pc++);
2812
        gen_op_movl_T0_im(val);
2813
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2814
        gen_op_out[ot]();
2815
        break;
2816
    case 0xec:
2817
    case 0xed:
2818
        if ((b & 1) == 0)
2819
            ot = OT_BYTE;
2820
        else
2821
            ot = dflag ? OT_LONG : OT_WORD;
2822
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2823
        gen_op_in[ot]();
2824
        gen_op_mov_reg_T1[ot][R_EAX]();
2825
        break;
2826
    case 0xee:
2827
    case 0xef:
2828
        if ((b & 1) == 0)
2829
            ot = OT_BYTE;
2830
        else
2831
            ot = dflag ? OT_LONG : OT_WORD;
2832
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2833
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2834
        gen_op_out[ot]();
2835
        break;
2836

    
2837
        /************************/
2838
        /* control */
2839
    case 0xc2: /* ret im */
2840
        val = ldsw(s->pc);
2841
        s->pc += 2;
2842
        gen_pop_T0(s);
2843
        if (s->ss32)
2844
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2845
        else
2846
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2847
        if (s->dflag == 0)
2848
            gen_op_andl_T0_ffff();
2849
        gen_op_jmp_T0();
2850
        s->is_jmp = 1;
2851
        break;
2852
    case 0xc3: /* ret */
2853
        gen_pop_T0(s);
2854
        gen_pop_update(s);
2855
        if (s->dflag == 0)
2856
            gen_op_andl_T0_ffff();
2857
        gen_op_jmp_T0();
2858
        s->is_jmp = 1;
2859
        break;
2860
    case 0xca: /* lret im */
2861
        /* XXX: not restartable */
2862
        val = ldsw(s->pc);
2863
        s->pc += 2;
2864
        /* pop offset */
2865
        gen_pop_T0(s);
2866
        if (s->dflag == 0)
2867
            gen_op_andl_T0_ffff();
2868
        gen_op_jmp_T0();
2869
        gen_pop_update(s);
2870
        /* pop selector */
2871
        gen_pop_T0(s);
2872
        gen_movl_seg_T0(s, R_CS);
2873
        gen_pop_update(s);
2874
        /* add stack offset */
2875
        if (s->ss32)
2876
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2877
        else
2878
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2879
        s->is_jmp = 1;
2880
        break;
2881
    case 0xcb: /* lret */
2882
        /* XXX: not restartable */
2883
        /* pop offset */
2884
        gen_pop_T0(s);
2885
        if (s->dflag == 0)
2886
            gen_op_andl_T0_ffff();
2887
        gen_op_jmp_T0();
2888
        gen_pop_update(s);
2889
        /* pop selector */
2890
        gen_pop_T0(s);
2891
        gen_movl_seg_T0(s, R_CS);
2892
        gen_pop_update(s);
2893
        s->is_jmp = 1;
2894
        break;
2895
    case 0xcf: /* iret */
2896
        /* XXX: not restartable */
2897
        /* pop offset */
2898
        gen_pop_T0(s);
2899
        if (s->dflag == 0)
2900
            gen_op_andl_T0_ffff();
2901
        gen_op_jmp_T0();
2902
        gen_pop_update(s);
2903
        /* pop selector */
2904
        gen_pop_T0(s);
2905
        gen_movl_seg_T0(s, R_CS);
2906
        gen_pop_update(s);
2907
        /* pop eflags */
2908
        gen_pop_T0(s);
2909
        if (s->dflag) {
2910
            if (s->vm86)
2911
                gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
2912
            else
2913
                gen_op_movl_eflags_T0();
2914
        } else {
2915
            if (s->vm86)
2916
                gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
2917
            else
2918
                gen_op_movw_eflags_T0();
2919
        }
2920
        gen_pop_update(s);
2921
        s->cc_op = CC_OP_EFLAGS;
2922
        s->is_jmp = 1;
2923
        break;
2924
    case 0xe8: /* call im */
2925
        {
2926
            unsigned int next_eip;
2927
            ot = dflag ? OT_LONG : OT_WORD;
2928
            val = insn_get(s, ot);
2929
            next_eip = s->pc - s->cs_base;
2930
            val += next_eip;
2931
            if (s->dflag == 0)
2932
                val &= 0xffff;
2933
            gen_op_movl_T0_im(next_eip);
2934
            gen_push_T0(s);
2935
            gen_op_jmp_im(val);
2936
            s->is_jmp = 1;
2937
        }
2938
        break;
2939
    case 0x9a: /* lcall im */
2940
        {
2941
            unsigned int selector, offset;
2942

    
2943
            ot = dflag ? OT_LONG : OT_WORD;
2944
            offset = insn_get(s, ot);
2945
            selector = insn_get(s, OT_WORD);
2946
            
2947
            /* push return segment + offset */
2948
            gen_op_movl_T0_seg(R_CS);
2949
            gen_push_T0(s);
2950
            next_eip = s->pc - s->cs_base;
2951
            gen_op_movl_T0_im(next_eip);
2952
            gen_push_T0(s);
2953

    
2954
            /* change cs and pc */
2955
            gen_op_movl_T0_im(selector);
2956
            gen_movl_seg_T0(s, R_CS);
2957
            gen_op_jmp_im((unsigned long)offset);
2958
            s->is_jmp = 1;
2959
        }
2960
        break;
2961
    case 0xe9: /* jmp */
2962
        ot = dflag ? OT_LONG : OT_WORD;
2963
        val = insn_get(s, ot);
2964
        val += s->pc - s->cs_base;
2965
        if (s->dflag == 0)
2966
            val = val & 0xffff;
2967
        gen_op_jmp_im(val);
2968
        s->is_jmp = 1;
2969
        break;
2970
    case 0xea: /* ljmp im */
2971
        {
2972
            unsigned int selector, offset;
2973

    
2974
            ot = dflag ? OT_LONG : OT_WORD;
2975
            offset = insn_get(s, ot);
2976
            selector = insn_get(s, OT_WORD);
2977
            
2978
            /* change cs and pc */
2979
            gen_op_movl_T0_im(selector);
2980
            gen_movl_seg_T0(s, R_CS);
2981
            gen_op_jmp_im((unsigned long)offset);
2982
            s->is_jmp = 1;
2983
        }
2984
        break;
2985
    case 0xeb: /* jmp Jb */
2986
        val = (int8_t)insn_get(s, OT_BYTE);
2987
        val += s->pc - s->cs_base;
2988
        if (s->dflag == 0)
2989
            val = val & 0xffff;
2990
        gen_op_jmp_im(val);
2991
        s->is_jmp = 1;
2992
        break;
2993
    case 0x70 ... 0x7f: /* jcc Jb */
2994
        val = (int8_t)insn_get(s, OT_BYTE);
2995
        goto do_jcc;
2996
    case 0x180 ... 0x18f: /* jcc Jv */
2997
        if (dflag) {
2998
            val = insn_get(s, OT_LONG);
2999
        } else {
3000
            val = (int16_t)insn_get(s, OT_WORD); 
3001
        }
3002
    do_jcc:
3003
        next_eip = s->pc - s->cs_base;
3004
        val += next_eip;
3005
        if (s->dflag == 0)
3006
            val &= 0xffff;
3007
        gen_jcc(s, b, val, next_eip);
3008
        s->is_jmp = 1;
3009
        break;
3010

    
3011
    case 0x190 ... 0x19f: /* setcc Gv */
3012
        modrm = ldub(s->pc++);
3013
        gen_setcc(s, b);
3014
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3015
        break;
3016
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3017
        ot = dflag ? OT_LONG : OT_WORD;
3018
        modrm = ldub(s->pc++);
3019
        reg = (modrm >> 3) & 7;
3020
        mod = (modrm >> 6) & 3;
3021
        gen_setcc(s, b);
3022
        if (mod != 3) {
3023
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3024
            gen_op_ld_T1_A0[ot]();
3025
        } else {
3026
            rm = modrm & 7;
3027
            gen_op_mov_TN_reg[ot][1][rm]();
3028
        }
3029
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3030
        break;
3031
        
3032
        /************************/
3033
        /* flags */
3034
    case 0x9c: /* pushf */
3035
        if (s->cc_op != CC_OP_DYNAMIC)
3036
            gen_op_set_cc_op(s->cc_op);
3037
        if (s->vm86)
3038
            gen_op_movl_T0_eflags_vm();
3039
        else
3040
            gen_op_movl_T0_eflags();
3041
        gen_push_T0(s);
3042
        break;
3043
    case 0x9d: /* popf */
3044
        gen_pop_T0(s);
3045
        if (s->dflag) {
3046
            if (s->vm86)
3047
                gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
3048
            else
3049
                gen_op_movl_eflags_T0();
3050
        } else {
3051
            if (s->vm86)
3052
                gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
3053
            else
3054
                gen_op_movw_eflags_T0();
3055
        }
3056
        gen_pop_update(s);
3057
        s->cc_op = CC_OP_EFLAGS;
3058
        break;
3059
    case 0x9e: /* sahf */
3060
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3061
        if (s->cc_op != CC_OP_DYNAMIC)
3062
            gen_op_set_cc_op(s->cc_op);
3063
        gen_op_movb_eflags_T0();
3064
        s->cc_op = CC_OP_EFLAGS;
3065
        break;
3066
    case 0x9f: /* lahf */
3067
        if (s->cc_op != CC_OP_DYNAMIC)
3068
            gen_op_set_cc_op(s->cc_op);
3069
        gen_op_movl_T0_eflags();
3070
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3071
        break;
3072
    case 0xf5: /* cmc */
3073
        if (s->cc_op != CC_OP_DYNAMIC)
3074
            gen_op_set_cc_op(s->cc_op);
3075
        gen_op_cmc();
3076
        s->cc_op = CC_OP_EFLAGS;
3077
        break;
3078
    case 0xf8: /* clc */
3079
        if (s->cc_op != CC_OP_DYNAMIC)
3080
            gen_op_set_cc_op(s->cc_op);
3081
        gen_op_clc();
3082
        s->cc_op = CC_OP_EFLAGS;
3083
        break;
3084
    case 0xf9: /* stc */
3085
        if (s->cc_op != CC_OP_DYNAMIC)
3086
            gen_op_set_cc_op(s->cc_op);
3087
        gen_op_stc();
3088
        s->cc_op = CC_OP_EFLAGS;
3089
        break;
3090
    case 0xfc: /* cld */
3091
        gen_op_cld();
3092
        break;
3093
    case 0xfd: /* std */
3094
        gen_op_std();
3095
        break;
3096

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

    
3301
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3302
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3303

    
3304
/* flags read by an operation */
3305
static uint16_t opc_read_flags[NB_OPS] = { 
3306
    [INDEX_op_aas] = CC_A,
3307
    [INDEX_op_aaa] = CC_A,
3308
    [INDEX_op_das] = CC_A | CC_C,
3309
    [INDEX_op_daa] = CC_A | CC_C,
3310

    
3311
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3312
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3313
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3314
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3315
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3316
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3317

    
3318
    [INDEX_op_into] = CC_O,
3319

    
3320
    [INDEX_op_jo_cc] = CC_O,
3321
    [INDEX_op_jb_cc] = CC_C,
3322
    [INDEX_op_jz_cc] = CC_Z,
3323
    [INDEX_op_jbe_cc] = CC_Z | CC_C,
3324
    [INDEX_op_js_cc] = CC_S,
3325
    [INDEX_op_jp_cc] = CC_P,
3326
    [INDEX_op_jl_cc] = CC_O | CC_S,
3327
    [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3328

    
3329
    [INDEX_op_jb_subb] = CC_C,
3330
    [INDEX_op_jb_subw] = CC_C,
3331
    [INDEX_op_jb_subl] = CC_C,
3332

    
3333
    [INDEX_op_jz_subb] = CC_Z,
3334
    [INDEX_op_jz_subw] = CC_Z,
3335
    [INDEX_op_jz_subl] = CC_Z,
3336

    
3337
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3338
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3339
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3340

    
3341
    [INDEX_op_js_subb] = CC_S,
3342
    [INDEX_op_js_subw] = CC_S,
3343
    [INDEX_op_js_subl] = CC_S,
3344

    
3345
    [INDEX_op_jl_subb] = CC_O | CC_S,
3346
    [INDEX_op_jl_subw] = CC_O | CC_S,
3347
    [INDEX_op_jl_subl] = CC_O | CC_S,
3348

    
3349
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3350
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3351
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3352

    
3353
    [INDEX_op_loopnzw] = CC_Z,
3354
    [INDEX_op_loopnzl] = CC_Z,
3355
    [INDEX_op_loopzw] = CC_Z,
3356
    [INDEX_op_loopzl] = CC_Z,
3357

    
3358
    [INDEX_op_seto_T0_cc] = CC_O,
3359
    [INDEX_op_setb_T0_cc] = CC_C,
3360
    [INDEX_op_setz_T0_cc] = CC_Z,
3361
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3362
    [INDEX_op_sets_T0_cc] = CC_S,
3363
    [INDEX_op_setp_T0_cc] = CC_P,
3364
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3365
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3366

    
3367
    [INDEX_op_setb_T0_subb] = CC_C,
3368
    [INDEX_op_setb_T0_subw] = CC_C,
3369
    [INDEX_op_setb_T0_subl] = CC_C,
3370

    
3371
    [INDEX_op_setz_T0_subb] = CC_Z,
3372
    [INDEX_op_setz_T0_subw] = CC_Z,
3373
    [INDEX_op_setz_T0_subl] = CC_Z,
3374

    
3375
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3376
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3377
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3378

    
3379
    [INDEX_op_sets_T0_subb] = CC_S,
3380
    [INDEX_op_sets_T0_subw] = CC_S,
3381
    [INDEX_op_sets_T0_subl] = CC_S,
3382

    
3383
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3384
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3385
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3386

    
3387
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3388
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3389
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3390

    
3391
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3392
    [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
3393
    [INDEX_op_cmc] = CC_C,
3394
    [INDEX_op_salc] = CC_C,
3395

    
3396
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3397
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3398
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3399
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3400
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3401
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3402
};
3403

    
3404
/* flags written by an operation */
3405
static uint16_t opc_write_flags[NB_OPS] = { 
3406
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3407
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3408
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3409
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3410
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3411
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3412
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3413
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3414
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3415
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3416
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3417
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3418
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3419
    [INDEX_op_incl_T0_cc] = CC_OSZAP,
3420
    [INDEX_op_decl_T0_cc] = CC_OSZAP,
3421
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3422

    
3423
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3424
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3425
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3426
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3427
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3428
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3429
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3430
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3431
    
3432
    /* bcd */
3433
    [INDEX_op_aam] = CC_OSZAPC,
3434
    [INDEX_op_aad] = CC_OSZAPC,
3435
    [INDEX_op_aas] = CC_OSZAPC,
3436
    [INDEX_op_aaa] = CC_OSZAPC,
3437
    [INDEX_op_das] = CC_OSZAPC,
3438
    [INDEX_op_daa] = CC_OSZAPC,
3439

    
3440
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3441
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3442
    [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC,
3443
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3444
    [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC,
3445
    [INDEX_op_clc] = CC_C,
3446
    [INDEX_op_stc] = CC_C,
3447
    [INDEX_op_cmc] = CC_C,
3448

    
3449
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3450
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3451
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3452
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3453
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3454
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3455

    
3456
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3457
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3458
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3459
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3460
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3461
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3462

    
3463
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3464
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3465
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3466

    
3467
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3468
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3469
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3470

    
3471
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3472
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3473
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3474

    
3475
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3476
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3477
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3478
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3479

    
3480
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3481
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3482
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3483
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3484

    
3485
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3486
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3487
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3488
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3489
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3490
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3491
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3492
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3493

    
3494
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3495
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3496
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3497
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3498

    
3499
#undef STRINGOP
3500
#define STRINGOP(x) \
3501
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3502
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3503
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3504
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3505
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3506
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3507
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3508
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3509
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3510

    
3511
    STRINGOP(scas)
3512
    STRINGOP(repz_scas)
3513
    STRINGOP(repnz_scas)
3514
    STRINGOP(cmps)
3515
    STRINGOP(repz_cmps)
3516
    STRINGOP(repnz_cmps)
3517

    
3518
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3519
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3520
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3521

    
3522
    [INDEX_op_cmpxchg8b] = CC_Z,
3523
};
3524

    
3525
/* simpler form of an operation if no flags need to be generated */
3526
static uint16_t opc_simpler[NB_OPS] = { 
3527
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3528
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3529
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3530
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3531
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3532
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3533
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3534
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3535

    
3536
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3537
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3538
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3539

    
3540
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3541
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3542
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3543

    
3544
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3545
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3546
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3547

    
3548
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3549
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3550
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3551

    
3552
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3553
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3554
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3555
};
3556

    
3557
static void optimize_flags_init(void)
3558
{
3559
    int i;
3560
    /* put default values in arrays */
3561
    for(i = 0; i < NB_OPS; i++) {
3562
        if (opc_simpler[i] == 0)
3563
            opc_simpler[i] = i;
3564
    }
3565
}
3566

    
3567
/* CPU flags computation optimization: we move backward thru the
3568
   generated code to see which flags are needed. The operation is
3569
   modified if suitable */
3570
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3571
{
3572
    uint16_t *opc_ptr;
3573
    int live_flags, write_flags, op;
3574

    
3575
    opc_ptr = opc_buf + opc_buf_len;
3576
    /* live_flags contains the flags needed by the next instructions
3577
       in the code. At the end of the bloc, we consider that all the
3578
       flags are live. */
3579
    live_flags = CC_OSZAPC;
3580
    while (opc_ptr > opc_buf) {
3581
        op = *--opc_ptr;
3582
        /* if none of the flags written by the instruction is used,
3583
           then we can try to find a simpler instruction */
3584
        write_flags = opc_write_flags[op];
3585
        if ((live_flags & write_flags) == 0) {
3586
            *opc_ptr = opc_simpler[op];
3587
        }
3588
        /* compute the live flags before the instruction */
3589
        live_flags &= ~write_flags;
3590
        live_flags |= opc_read_flags[op];
3591
    }
3592
}
3593

    
3594

    
3595
#ifdef DEBUG_DISAS
3596
static const char *op_str[] = {
3597
#define DEF(s, n) #s,
3598
#include "opc-i386.h"
3599
#undef DEF
3600
};
3601

    
3602
static uint8_t op_nb_args[] = {
3603
#define DEF(s, n) n,
3604
#include "opc-i386.h"
3605
#undef DEF
3606
};
3607

    
3608
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3609
{
3610
    const uint16_t *opc_ptr;
3611
    const uint32_t *opparam_ptr;
3612
    int c, n, i;
3613

    
3614
    opc_ptr = opc_buf;
3615
    opparam_ptr = opparam_buf;
3616
    for(;;) {
3617
        c = *opc_ptr++;
3618
        n = op_nb_args[c];
3619
        fprintf(logfile, "0x%04x: %s", opc_ptr - opc_buf - 1, op_str[c]);
3620
        for(i = 0; i < n; i++) {
3621
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
3622
        }
3623
        fprintf(logfile, "\n");
3624
        if (c == INDEX_op_end)
3625
            break;
3626
        opparam_ptr += n;
3627
    }
3628
}
3629

    
3630
#endif
3631

    
3632
/* XXX: make this buffer thread safe */
3633
/* XXX: make safe guess about sizes */
3634
#define MAX_OP_PER_INSTR 32
3635
#define OPC_BUF_SIZE 512
3636
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3637

    
3638
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3639

    
3640
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3641
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3642

    
3643
/* return non zero if the very first instruction is invalid so that
3644
   the virtual CPU can trigger an exception. */
3645
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3646
                     int *gen_code_size_ptr,
3647
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3648
{
3649
    DisasContext dc1, *dc = &dc1;
3650
    uint8_t *pc_ptr;
3651
    uint16_t *gen_opc_end;
3652
    int gen_code_size;
3653
    long ret;
3654
    
3655
    /* generate intermediate code */
3656

    
3657
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3658
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3659
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3660
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3661
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3662
    dc->cc_op = CC_OP_DYNAMIC;
3663
    dc->cs_base = cs_base;
3664

    
3665
    gen_opc_ptr = gen_opc_buf;
3666
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3667
    gen_opparam_ptr = gen_opparam_buf;
3668

    
3669
    dc->is_jmp = 0;
3670
    pc_ptr = pc_start;
3671
    do {
3672
        ret = disas_insn(dc, pc_ptr);
3673
        if (ret == -1) {
3674
            /* we trigger an illegal instruction operation only if it
3675
               is the first instruction. Otherwise, we simply stop
3676
               generating the code just before it */
3677
            if (pc_ptr == pc_start)
3678
                return -1;
3679
            else
3680
                break;
3681
        }
3682
        pc_ptr = (void *)ret;
3683
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3684
    /* we must store the eflags state if it is not already done */
3685
    if (dc->cc_op != CC_OP_DYNAMIC)
3686
        gen_op_set_cc_op(dc->cc_op);
3687
    if (dc->is_jmp != 1) {
3688
        /* we add an additionnal jmp to update the simulated PC */
3689
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3690
    }
3691
    *gen_opc_ptr = INDEX_op_end;
3692

    
3693
#ifdef DEBUG_DISAS
3694
    if (loglevel) {
3695
        fprintf(logfile, "----------------\n");
3696
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3697
        disas(logfile, pc_start, pc_ptr - pc_start,
3698
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3699
        fprintf(logfile, "\n");
3700
        
3701
        fprintf(logfile, "OP:\n");
3702
        dump_ops(gen_opc_buf, gen_opparam_buf);
3703
        fprintf(logfile, "\n");
3704
    }
3705
#endif
3706

    
3707
    /* optimize flag computations */
3708
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3709

    
3710
#ifdef DEBUG_DISAS
3711
    if (loglevel) {
3712
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3713
        dump_ops(gen_opc_buf, gen_opparam_buf);
3714
        fprintf(logfile, "\n");
3715
    }
3716
#endif
3717

    
3718
    /* generate machine code */
3719
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3720
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3721
    *gen_code_size_ptr = gen_code_size;
3722

    
3723
#ifdef DEBUG_DISAS
3724
    if (loglevel) {
3725
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3726
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3727
        fprintf(logfile, "\n");
3728
        fflush(logfile);
3729
    }
3730
#endif
3731
    return 0;
3732
}
3733

    
3734
CPUX86State *cpu_x86_init(void)
3735
{
3736
    CPUX86State *env;
3737
    int i;
3738
    static int inited;
3739

    
3740
    cpu_x86_tblocks_init();
3741

    
3742
    env = malloc(sizeof(CPUX86State));
3743
    if (!env)
3744
        return NULL;
3745
    memset(env, 0, sizeof(CPUX86State));
3746
    /* basic FPU init */
3747
    for(i = 0;i < 8; i++)
3748
        env->fptags[i] = 1;
3749
    env->fpuc = 0x37f;
3750
    /* flags setup : we activate the IRQs by default as in user mode */
3751
    env->eflags = 0x2 | IF_MASK;
3752

    
3753
    /* init various static tables */
3754
    if (!inited) {
3755
        inited = 1;
3756
        optimize_flags_init();
3757
    }
3758
    return env;
3759
}
3760

    
3761
void cpu_x86_close(CPUX86State *env)
3762
{
3763
    free(env);
3764
}