Statistics
| Branch: | Revision:

root / translate-i386.c @ fe1e3ce3

History | View | Annotate | Download (100 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 __powerpc__
57

    
58
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
59

    
60
static void inline flush_icache_range(unsigned long start, unsigned long stop)
61
{
62
    unsigned long p;
63

    
64
    p = start & ~(MIN_CACHE_LINE_SIZE - 1);
65
    stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
66
    
67
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
68
        asm ("dcbst 0,%0;" : : "r"(p) : "memory");
69
    }
70
    asm ("sync");
71
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
72
        asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
73
    }
74
    asm ("sync");
75
    asm ("isync");
76
}
77
#endif
78

    
79
extern FILE *logfile;
80
extern int loglevel;
81

    
82
#define PREFIX_REPZ   0x01
83
#define PREFIX_REPNZ  0x02
84
#define PREFIX_LOCK   0x04
85
#define PREFIX_DATA   0x08
86
#define PREFIX_ADR    0x10
87
#define PREFIX_FWAIT  0x20
88

    
89
typedef struct DisasContext {
90
    /* current insn context */
91
    int override; /* -1 if no override */
92
    int prefix;
93
    int aflag, dflag;
94
    uint8_t *pc; /* pc = eip + cs_base */
95
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
96
                   static state change (stop translation) */
97
    /* current block context */
98
    uint8_t *cs_base; /* base of CS segment */
99
    int code32; /* 32 bit code segment */
100
    int ss32;   /* 32 bit stack segment */
101
    int cc_op;  /* current CC operation */
102
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
103
    int f_st;   /* currently unused */
104
    int vm86;   /* vm86 mode */
105
} DisasContext;
106

    
107
/* i386 arith/logic operations */
108
enum {
109
    OP_ADDL, 
110
    OP_ORL, 
111
    OP_ADCL, 
112
    OP_SBBL,
113
    OP_ANDL, 
114
    OP_SUBL, 
115
    OP_XORL, 
116
    OP_CMPL,
117
};
118

    
119
/* i386 shift ops */
120
enum {
121
    OP_ROL, 
122
    OP_ROR, 
123
    OP_RCL, 
124
    OP_RCR, 
125
    OP_SHL, 
126
    OP_SHR, 
127
    OP_SHL1, /* undocumented */
128
    OP_SAR = 7,
129
};
130

    
131
enum {
132
#define DEF(s, n) INDEX_op_ ## s,
133
#include "opc-i386.h"
134
#undef DEF
135
    NB_OPS,
136
};
137

    
138
#include "op-i386.h"
139

    
140
/* operand size */
141
enum {
142
    OT_BYTE = 0,
143
    OT_WORD,
144
    OT_LONG, 
145
    OT_QUAD,
146
};
147

    
148
enum {
149
    /* I386 int registers */
150
    OR_EAX,   /* MUST be even numbered */
151
    OR_ECX,
152
    OR_EDX,
153
    OR_EBX,
154
    OR_ESP,
155
    OR_EBP,
156
    OR_ESI,
157
    OR_EDI,
158
    OR_TMP0,    /* temporary operand register */
159
    OR_TMP1,
160
    OR_A0, /* temporary register used when doing address evaluation */
161
    OR_ZERO, /* fixed zero register */
162
    NB_OREGS,
163
};
164

    
165
typedef void (GenOpFunc)(void);
166
typedef void (GenOpFunc1)(long);
167
typedef void (GenOpFunc2)(long, long);
168
                    
169
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
170
    [OT_BYTE] = {
171
        gen_op_movb_EAX_T0,
172
        gen_op_movb_ECX_T0,
173
        gen_op_movb_EDX_T0,
174
        gen_op_movb_EBX_T0,
175
        gen_op_movh_EAX_T0,
176
        gen_op_movh_ECX_T0,
177
        gen_op_movh_EDX_T0,
178
        gen_op_movh_EBX_T0,
179
    },
180
    [OT_WORD] = {
181
        gen_op_movw_EAX_T0,
182
        gen_op_movw_ECX_T0,
183
        gen_op_movw_EDX_T0,
184
        gen_op_movw_EBX_T0,
185
        gen_op_movw_ESP_T0,
186
        gen_op_movw_EBP_T0,
187
        gen_op_movw_ESI_T0,
188
        gen_op_movw_EDI_T0,
189
    },
190
    [OT_LONG] = {
191
        gen_op_movl_EAX_T0,
192
        gen_op_movl_ECX_T0,
193
        gen_op_movl_EDX_T0,
194
        gen_op_movl_EBX_T0,
195
        gen_op_movl_ESP_T0,
196
        gen_op_movl_EBP_T0,
197
        gen_op_movl_ESI_T0,
198
        gen_op_movl_EDI_T0,
199
    },
200
};
201

    
202
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
203
    [OT_BYTE] = {
204
        gen_op_movb_EAX_T1,
205
        gen_op_movb_ECX_T1,
206
        gen_op_movb_EDX_T1,
207
        gen_op_movb_EBX_T1,
208
        gen_op_movh_EAX_T1,
209
        gen_op_movh_ECX_T1,
210
        gen_op_movh_EDX_T1,
211
        gen_op_movh_EBX_T1,
212
    },
213
    [OT_WORD] = {
214
        gen_op_movw_EAX_T1,
215
        gen_op_movw_ECX_T1,
216
        gen_op_movw_EDX_T1,
217
        gen_op_movw_EBX_T1,
218
        gen_op_movw_ESP_T1,
219
        gen_op_movw_EBP_T1,
220
        gen_op_movw_ESI_T1,
221
        gen_op_movw_EDI_T1,
222
    },
223
    [OT_LONG] = {
224
        gen_op_movl_EAX_T1,
225
        gen_op_movl_ECX_T1,
226
        gen_op_movl_EDX_T1,
227
        gen_op_movl_EBX_T1,
228
        gen_op_movl_ESP_T1,
229
        gen_op_movl_EBP_T1,
230
        gen_op_movl_ESI_T1,
231
        gen_op_movl_EDI_T1,
232
    },
233
};
234

    
235
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
236
    [0] = {
237
        gen_op_movw_EAX_A0,
238
        gen_op_movw_ECX_A0,
239
        gen_op_movw_EDX_A0,
240
        gen_op_movw_EBX_A0,
241
        gen_op_movw_ESP_A0,
242
        gen_op_movw_EBP_A0,
243
        gen_op_movw_ESI_A0,
244
        gen_op_movw_EDI_A0,
245
    },
246
    [1] = {
247
        gen_op_movl_EAX_A0,
248
        gen_op_movl_ECX_A0,
249
        gen_op_movl_EDX_A0,
250
        gen_op_movl_EBX_A0,
251
        gen_op_movl_ESP_A0,
252
        gen_op_movl_EBP_A0,
253
        gen_op_movl_ESI_A0,
254
        gen_op_movl_EDI_A0,
255
    },
256
};
257

    
258
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
259
{
260
    [OT_BYTE] = {
261
        {
262
            gen_op_movl_T0_EAX,
263
            gen_op_movl_T0_ECX,
264
            gen_op_movl_T0_EDX,
265
            gen_op_movl_T0_EBX,
266
            gen_op_movh_T0_EAX,
267
            gen_op_movh_T0_ECX,
268
            gen_op_movh_T0_EDX,
269
            gen_op_movh_T0_EBX,
270
        },
271
        {
272
            gen_op_movl_T1_EAX,
273
            gen_op_movl_T1_ECX,
274
            gen_op_movl_T1_EDX,
275
            gen_op_movl_T1_EBX,
276
            gen_op_movh_T1_EAX,
277
            gen_op_movh_T1_ECX,
278
            gen_op_movh_T1_EDX,
279
            gen_op_movh_T1_EBX,
280
        },
281
    },
282
    [OT_WORD] = {
283
        {
284
            gen_op_movl_T0_EAX,
285
            gen_op_movl_T0_ECX,
286
            gen_op_movl_T0_EDX,
287
            gen_op_movl_T0_EBX,
288
            gen_op_movl_T0_ESP,
289
            gen_op_movl_T0_EBP,
290
            gen_op_movl_T0_ESI,
291
            gen_op_movl_T0_EDI,
292
        },
293
        {
294
            gen_op_movl_T1_EAX,
295
            gen_op_movl_T1_ECX,
296
            gen_op_movl_T1_EDX,
297
            gen_op_movl_T1_EBX,
298
            gen_op_movl_T1_ESP,
299
            gen_op_movl_T1_EBP,
300
            gen_op_movl_T1_ESI,
301
            gen_op_movl_T1_EDI,
302
        },
303
    },
304
    [OT_LONG] = {
305
        {
306
            gen_op_movl_T0_EAX,
307
            gen_op_movl_T0_ECX,
308
            gen_op_movl_T0_EDX,
309
            gen_op_movl_T0_EBX,
310
            gen_op_movl_T0_ESP,
311
            gen_op_movl_T0_EBP,
312
            gen_op_movl_T0_ESI,
313
            gen_op_movl_T0_EDI,
314
        },
315
        {
316
            gen_op_movl_T1_EAX,
317
            gen_op_movl_T1_ECX,
318
            gen_op_movl_T1_EDX,
319
            gen_op_movl_T1_EBX,
320
            gen_op_movl_T1_ESP,
321
            gen_op_movl_T1_EBP,
322
            gen_op_movl_T1_ESI,
323
            gen_op_movl_T1_EDI,
324
        },
325
    },
326
};
327

    
328
static GenOpFunc *gen_op_movl_A0_reg[8] = {
329
    gen_op_movl_A0_EAX,
330
    gen_op_movl_A0_ECX,
331
    gen_op_movl_A0_EDX,
332
    gen_op_movl_A0_EBX,
333
    gen_op_movl_A0_ESP,
334
    gen_op_movl_A0_EBP,
335
    gen_op_movl_A0_ESI,
336
    gen_op_movl_A0_EDI,
337
};
338

    
339
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
340
    [0] = {
341
        gen_op_addl_A0_EAX,
342
        gen_op_addl_A0_ECX,
343
        gen_op_addl_A0_EDX,
344
        gen_op_addl_A0_EBX,
345
        gen_op_addl_A0_ESP,
346
        gen_op_addl_A0_EBP,
347
        gen_op_addl_A0_ESI,
348
        gen_op_addl_A0_EDI,
349
    },
350
    [1] = {
351
        gen_op_addl_A0_EAX_s1,
352
        gen_op_addl_A0_ECX_s1,
353
        gen_op_addl_A0_EDX_s1,
354
        gen_op_addl_A0_EBX_s1,
355
        gen_op_addl_A0_ESP_s1,
356
        gen_op_addl_A0_EBP_s1,
357
        gen_op_addl_A0_ESI_s1,
358
        gen_op_addl_A0_EDI_s1,
359
    },
360
    [2] = {
361
        gen_op_addl_A0_EAX_s2,
362
        gen_op_addl_A0_ECX_s2,
363
        gen_op_addl_A0_EDX_s2,
364
        gen_op_addl_A0_EBX_s2,
365
        gen_op_addl_A0_ESP_s2,
366
        gen_op_addl_A0_EBP_s2,
367
        gen_op_addl_A0_ESI_s2,
368
        gen_op_addl_A0_EDI_s2,
369
    },
370
    [3] = {
371
        gen_op_addl_A0_EAX_s3,
372
        gen_op_addl_A0_ECX_s3,
373
        gen_op_addl_A0_EDX_s3,
374
        gen_op_addl_A0_EBX_s3,
375
        gen_op_addl_A0_ESP_s3,
376
        gen_op_addl_A0_EBP_s3,
377
        gen_op_addl_A0_ESI_s3,
378
        gen_op_addl_A0_EDI_s3,
379
    },
380
};
381

    
382
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
383
    [0] = {
384
        gen_op_cmovw_EAX_T1_T0,
385
        gen_op_cmovw_ECX_T1_T0,
386
        gen_op_cmovw_EDX_T1_T0,
387
        gen_op_cmovw_EBX_T1_T0,
388
        gen_op_cmovw_ESP_T1_T0,
389
        gen_op_cmovw_EBP_T1_T0,
390
        gen_op_cmovw_ESI_T1_T0,
391
        gen_op_cmovw_EDI_T1_T0,
392
    },
393
    [1] = {
394
        gen_op_cmovl_EAX_T1_T0,
395
        gen_op_cmovl_ECX_T1_T0,
396
        gen_op_cmovl_EDX_T1_T0,
397
        gen_op_cmovl_EBX_T1_T0,
398
        gen_op_cmovl_ESP_T1_T0,
399
        gen_op_cmovl_EBP_T1_T0,
400
        gen_op_cmovl_ESI_T1_T0,
401
        gen_op_cmovl_EDI_T1_T0,
402
    },
403
};
404

    
405
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
406
    gen_op_addl_T0_T1_cc,
407
    gen_op_orl_T0_T1_cc,
408
    NULL,
409
    NULL,
410
    gen_op_andl_T0_T1_cc,
411
    gen_op_subl_T0_T1_cc,
412
    gen_op_xorl_T0_T1_cc,
413
    gen_op_cmpl_T0_T1_cc,
414
};
415

    
416
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
417
    [OT_BYTE] = {
418
        gen_op_adcb_T0_T1_cc,
419
        gen_op_sbbb_T0_T1_cc,
420
    },
421
    [OT_WORD] = {
422
        gen_op_adcw_T0_T1_cc,
423
        gen_op_sbbw_T0_T1_cc,
424
    },
425
    [OT_LONG] = {
426
        gen_op_adcl_T0_T1_cc,
427
        gen_op_sbbl_T0_T1_cc,
428
    },
429
};
430

    
431
static const int cc_op_arithb[8] = {
432
    CC_OP_ADDB,
433
    CC_OP_LOGICB,
434
    CC_OP_ADDB,
435
    CC_OP_SUBB,
436
    CC_OP_LOGICB,
437
    CC_OP_SUBB,
438
    CC_OP_LOGICB,
439
    CC_OP_SUBB,
440
};
441

    
442
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
443
    gen_op_cmpxchgb_T0_T1_EAX_cc,
444
    gen_op_cmpxchgw_T0_T1_EAX_cc,
445
    gen_op_cmpxchgl_T0_T1_EAX_cc,
446
};
447

    
448
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
449
    [OT_BYTE] = {
450
        gen_op_rolb_T0_T1_cc,
451
        gen_op_rorb_T0_T1_cc,
452
        gen_op_rclb_T0_T1_cc,
453
        gen_op_rcrb_T0_T1_cc,
454
        gen_op_shlb_T0_T1_cc,
455
        gen_op_shrb_T0_T1_cc,
456
        gen_op_shlb_T0_T1_cc,
457
        gen_op_sarb_T0_T1_cc,
458
    },
459
    [OT_WORD] = {
460
        gen_op_rolw_T0_T1_cc,
461
        gen_op_rorw_T0_T1_cc,
462
        gen_op_rclw_T0_T1_cc,
463
        gen_op_rcrw_T0_T1_cc,
464
        gen_op_shlw_T0_T1_cc,
465
        gen_op_shrw_T0_T1_cc,
466
        gen_op_shlw_T0_T1_cc,
467
        gen_op_sarw_T0_T1_cc,
468
    },
469
    [OT_LONG] = {
470
        gen_op_roll_T0_T1_cc,
471
        gen_op_rorl_T0_T1_cc,
472
        gen_op_rcll_T0_T1_cc,
473
        gen_op_rcrl_T0_T1_cc,
474
        gen_op_shll_T0_T1_cc,
475
        gen_op_shrl_T0_T1_cc,
476
        gen_op_shll_T0_T1_cc,
477
        gen_op_sarl_T0_T1_cc,
478
    },
479
};
480

    
481
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
482
    [0] = {
483
        gen_op_shldw_T0_T1_im_cc,
484
        gen_op_shrdw_T0_T1_im_cc,
485
    },
486
    [1] = {
487
        gen_op_shldl_T0_T1_im_cc,
488
        gen_op_shrdl_T0_T1_im_cc,
489
    },
490
};
491

    
492
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
493
    [0] = {
494
        gen_op_shldw_T0_T1_ECX_cc,
495
        gen_op_shrdw_T0_T1_ECX_cc,
496
    },
497
    [1] = {
498
        gen_op_shldl_T0_T1_ECX_cc,
499
        gen_op_shrdl_T0_T1_ECX_cc,
500
    },
501
};
502

    
503
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
504
    [0] = {
505
        gen_op_btw_T0_T1_cc,
506
        gen_op_btsw_T0_T1_cc,
507
        gen_op_btrw_T0_T1_cc,
508
        gen_op_btcw_T0_T1_cc,
509
    },
510
    [1] = {
511
        gen_op_btl_T0_T1_cc,
512
        gen_op_btsl_T0_T1_cc,
513
        gen_op_btrl_T0_T1_cc,
514
        gen_op_btcl_T0_T1_cc,
515
    },
516
};
517

    
518
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
519
    [0] = {
520
        gen_op_bsfw_T0_cc,
521
        gen_op_bsrw_T0_cc,
522
    },
523
    [1] = {
524
        gen_op_bsfl_T0_cc,
525
        gen_op_bsrl_T0_cc,
526
    },
527
};
528

    
529
static GenOpFunc *gen_op_lds_T0_A0[3] = {
530
    gen_op_ldsb_T0_A0,
531
    gen_op_ldsw_T0_A0,
532
};
533

    
534
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
535
    gen_op_ldub_T0_A0,
536
    gen_op_lduw_T0_A0,
537
};
538

    
539
/* sign does not matter */
540
static GenOpFunc *gen_op_ld_T0_A0[3] = {
541
    gen_op_ldub_T0_A0,
542
    gen_op_lduw_T0_A0,
543
    gen_op_ldl_T0_A0,
544
};
545

    
546
static GenOpFunc *gen_op_ld_T1_A0[3] = {
547
    gen_op_ldub_T1_A0,
548
    gen_op_lduw_T1_A0,
549
    gen_op_ldl_T1_A0,
550
};
551

    
552
static GenOpFunc *gen_op_st_T0_A0[3] = {
553
    gen_op_stb_T0_A0,
554
    gen_op_stw_T0_A0,
555
    gen_op_stl_T0_A0,
556
};
557

    
558
/* the _a32 and _a16 string operations use A0 as the base register. */
559

    
560
#define STRINGOP(x) \
561
    gen_op_ ## x ## b_fast, \
562
    gen_op_ ## x ## w_fast, \
563
    gen_op_ ## x ## l_fast, \
564
    gen_op_ ## x ## b_a32, \
565
    gen_op_ ## x ## w_a32, \
566
    gen_op_ ## x ## l_a32, \
567
    gen_op_ ## x ## b_a16, \
568
    gen_op_ ## x ## w_a16, \
569
    gen_op_ ## x ## l_a16,
570
     
571
static GenOpFunc *gen_op_movs[9 * 2] = {
572
    STRINGOP(movs)
573
    STRINGOP(rep_movs)
574
};
575

    
576
static GenOpFunc *gen_op_stos[9 * 2] = {
577
    STRINGOP(stos)
578
    STRINGOP(rep_stos)
579
};
580

    
581
static GenOpFunc *gen_op_lods[9 * 2] = {
582
    STRINGOP(lods)
583
    STRINGOP(rep_lods)
584
};
585

    
586
static GenOpFunc *gen_op_scas[9 * 3] = {
587
    STRINGOP(scas)
588
    STRINGOP(repz_scas)
589
    STRINGOP(repnz_scas)
590
};
591

    
592
static GenOpFunc *gen_op_cmps[9 * 3] = {
593
    STRINGOP(cmps)
594
    STRINGOP(repz_cmps)
595
    STRINGOP(repnz_cmps)
596
};
597

    
598
static GenOpFunc *gen_op_ins[9 * 2] = {
599
    STRINGOP(ins)
600
    STRINGOP(rep_ins)
601
};
602

    
603

    
604
static GenOpFunc *gen_op_outs[9 * 2] = {
605
    STRINGOP(outs)
606
    STRINGOP(rep_outs)
607
};
608

    
609

    
610
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
611
{
612
    int index, override;
613

    
614
    override = s->override;
615
    if (s->aflag) {
616
        /* 32 bit address */
617
        if (s->addseg && override < 0)
618
            override = R_DS;
619
        if (override >= 0) {
620
            gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
621
            index = 3 + ot;
622
        } else {
623
            index = ot;
624
        }
625
    } else {
626
        if (override < 0)
627
            override = R_DS;
628
        gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
629
        /* 16 address, always override */
630
        index = 6 + ot;
631
    }
632
    func[index]();
633
}
634

    
635
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
636
{
637
    int index;
638
            
639
    if (s->aflag) {
640
        if (s->addseg) {
641
            index = 3 + ot;
642
        } else {
643
            index = ot;
644
        }
645
    } else {
646
        index = 6 + ot;
647
    }
648
    func[index]();
649
}
650

    
651

    
652
static GenOpFunc *gen_op_in[3] = {
653
    gen_op_inb_T0_T1,
654
    gen_op_inw_T0_T1,
655
    gen_op_inl_T0_T1,
656
};
657

    
658
static GenOpFunc *gen_op_out[3] = {
659
    gen_op_outb_T0_T1,
660
    gen_op_outw_T0_T1,
661
    gen_op_outl_T0_T1,
662
};
663

    
664
enum {
665
    JCC_O,
666
    JCC_B,
667
    JCC_Z,
668
    JCC_BE,
669
    JCC_S,
670
    JCC_P,
671
    JCC_L,
672
    JCC_LE,
673
};
674

    
675
static GenOpFunc2 *gen_jcc_slow[8] = {
676
    gen_op_jo_cc,
677
    gen_op_jb_cc,
678
    gen_op_jz_cc,
679
    gen_op_jbe_cc,
680
    gen_op_js_cc,
681
    gen_op_jp_cc,
682
    gen_op_jl_cc,
683
    gen_op_jle_cc,
684
};
685
    
686
static GenOpFunc2 *gen_jcc_sub[3][8] = {
687
    [OT_BYTE] = {
688
        NULL,
689
        gen_op_jb_subb,
690
        gen_op_jz_subb,
691
        gen_op_jbe_subb,
692
        gen_op_js_subb,
693
        NULL,
694
        gen_op_jl_subb,
695
        gen_op_jle_subb,
696
    },
697
    [OT_WORD] = {
698
        NULL,
699
        gen_op_jb_subw,
700
        gen_op_jz_subw,
701
        gen_op_jbe_subw,
702
        gen_op_js_subw,
703
        NULL,
704
        gen_op_jl_subw,
705
        gen_op_jle_subw,
706
    },
707
    [OT_LONG] = {
708
        NULL,
709
        gen_op_jb_subl,
710
        gen_op_jz_subl,
711
        gen_op_jbe_subl,
712
        gen_op_js_subl,
713
        NULL,
714
        gen_op_jl_subl,
715
        gen_op_jle_subl,
716
    },
717
};
718
static GenOpFunc2 *gen_op_loop[2][4] = {
719
    [0] = {
720
        gen_op_loopnzw,
721
        gen_op_loopzw,
722
        gen_op_loopw,
723
        gen_op_jecxzw,
724
    },
725
    [1] = {
726
        gen_op_loopnzl,
727
        gen_op_loopzl,
728
        gen_op_loopl,
729
        gen_op_jecxzl,
730
    },
731
};
732

    
733
static GenOpFunc *gen_setcc_slow[8] = {
734
    gen_op_seto_T0_cc,
735
    gen_op_setb_T0_cc,
736
    gen_op_setz_T0_cc,
737
    gen_op_setbe_T0_cc,
738
    gen_op_sets_T0_cc,
739
    gen_op_setp_T0_cc,
740
    gen_op_setl_T0_cc,
741
    gen_op_setle_T0_cc,
742
};
743

    
744
static GenOpFunc *gen_setcc_sub[3][8] = {
745
    [OT_BYTE] = {
746
        NULL,
747
        gen_op_setb_T0_subb,
748
        gen_op_setz_T0_subb,
749
        gen_op_setbe_T0_subb,
750
        gen_op_sets_T0_subb,
751
        NULL,
752
        gen_op_setl_T0_subb,
753
        gen_op_setle_T0_subb,
754
    },
755
    [OT_WORD] = {
756
        NULL,
757
        gen_op_setb_T0_subw,
758
        gen_op_setz_T0_subw,
759
        gen_op_setbe_T0_subw,
760
        gen_op_sets_T0_subw,
761
        NULL,
762
        gen_op_setl_T0_subw,
763
        gen_op_setle_T0_subw,
764
    },
765
    [OT_LONG] = {
766
        NULL,
767
        gen_op_setb_T0_subl,
768
        gen_op_setz_T0_subl,
769
        gen_op_setbe_T0_subl,
770
        gen_op_sets_T0_subl,
771
        NULL,
772
        gen_op_setl_T0_subl,
773
        gen_op_setle_T0_subl,
774
    },
775
};
776

    
777
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
778
    gen_op_fadd_ST0_FT0,
779
    gen_op_fmul_ST0_FT0,
780
    gen_op_fcom_ST0_FT0,
781
    gen_op_fcom_ST0_FT0,
782
    gen_op_fsub_ST0_FT0,
783
    gen_op_fsubr_ST0_FT0,
784
    gen_op_fdiv_ST0_FT0,
785
    gen_op_fdivr_ST0_FT0,
786
};
787

    
788
/* NOTE the exception in "r" op ordering */
789
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
790
    gen_op_fadd_STN_ST0,
791
    gen_op_fmul_STN_ST0,
792
    NULL,
793
    NULL,
794
    gen_op_fsubr_STN_ST0,
795
    gen_op_fsub_STN_ST0,
796
    gen_op_fdivr_STN_ST0,
797
    gen_op_fdiv_STN_ST0,
798
};
799

    
800
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
801
{
802
    if (d != OR_TMP0)
803
        gen_op_mov_TN_reg[ot][0][d]();
804
    if (s != OR_TMP1)
805
        gen_op_mov_TN_reg[ot][1][s]();
806
    if (op == OP_ADCL || op == OP_SBBL) {
807
        if (s1->cc_op != CC_OP_DYNAMIC)
808
            gen_op_set_cc_op(s1->cc_op);
809
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
810
        s1->cc_op = CC_OP_DYNAMIC;
811
    } else {
812
        gen_op_arith_T0_T1_cc[op]();
813
        s1->cc_op = cc_op_arithb[op] + ot;
814
    }
815
    if (d != OR_TMP0 && op != OP_CMPL)
816
        gen_op_mov_reg_T0[ot][d]();
817
}
818

    
819
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
820
{
821
    gen_op_movl_T1_im(c);
822
    gen_op(s1, op, ot, d, OR_TMP1);
823
}
824

    
825
static void gen_inc(DisasContext *s1, int ot, int d, int c)
826
{
827
    if (d != OR_TMP0)
828
        gen_op_mov_TN_reg[ot][0][d]();
829
    if (s1->cc_op != CC_OP_DYNAMIC)
830
        gen_op_set_cc_op(s1->cc_op);
831
    if (c > 0) {
832
        gen_op_incl_T0_cc();
833
        s1->cc_op = CC_OP_INCB + ot;
834
    } else {
835
        gen_op_decl_T0_cc();
836
        s1->cc_op = CC_OP_DECB + ot;
837
    }
838
    if (d != OR_TMP0)
839
        gen_op_mov_reg_T0[ot][d]();
840
}
841

    
842
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
843
{
844
    if (d != OR_TMP0)
845
        gen_op_mov_TN_reg[ot][0][d]();
846
    if (s != OR_TMP1)
847
        gen_op_mov_TN_reg[ot][1][s]();
848
    /* for zero counts, flags are not updated, so must do it dynamically */
849
    if (s1->cc_op != CC_OP_DYNAMIC)
850
        gen_op_set_cc_op(s1->cc_op);
851

    
852
    gen_op_shift_T0_T1_cc[ot][op]();
853

    
854
    if (d != OR_TMP0)
855
        gen_op_mov_reg_T0[ot][d]();
856
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
857
}
858

    
859
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
860
{
861
    /* currently not optimized */
862
    gen_op_movl_T1_im(c);
863
    gen_shift(s1, op, ot, d, OR_TMP1);
864
}
865

    
866
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
867
{
868
    int havesib;
869
    int base, disp;
870
    int index;
871
    int scale;
872
    int opreg;
873
    int mod, rm, code, override, must_add_seg;
874

    
875
    override = s->override;
876
    must_add_seg = s->addseg;
877
    if (override >= 0)
878
        must_add_seg = 1;
879
    mod = (modrm >> 6) & 3;
880
    rm = modrm & 7;
881

    
882
    if (s->aflag) {
883

    
884
        havesib = 0;
885
        base = rm;
886
        index = 0;
887
        scale = 0;
888
        
889
        if (base == 4) {
890
            havesib = 1;
891
            code = ldub(s->pc++);
892
            scale = (code >> 6) & 3;
893
            index = (code >> 3) & 7;
894
            base = code & 7;
895
        }
896

    
897
        switch (mod) {
898
        case 0:
899
            if (base == 5) {
900
                base = -1;
901
                disp = ldl(s->pc);
902
                s->pc += 4;
903
            } else {
904
                disp = 0;
905
            }
906
            break;
907
        case 1:
908
            disp = (int8_t)ldub(s->pc++);
909
            break;
910
        default:
911
        case 2:
912
            disp = ldl(s->pc);
913
            s->pc += 4;
914
            break;
915
        }
916
        
917
        if (base >= 0) {
918
            gen_op_movl_A0_reg[base]();
919
            if (disp != 0)
920
                gen_op_addl_A0_im(disp);
921
        } else {
922
            gen_op_movl_A0_im(disp);
923
        }
924
        if (havesib && (index != 4 || scale != 0)) {
925
            gen_op_addl_A0_reg_sN[scale][index]();
926
        }
927
        if (must_add_seg) {
928
            if (override < 0) {
929
                if (base == R_EBP || base == R_ESP)
930
                    override = R_SS;
931
                else
932
                    override = R_DS;
933
            }
934
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
935
        }
936
    } else {
937
        switch (mod) {
938
        case 0:
939
            if (rm == 6) {
940
                disp = lduw(s->pc);
941
                s->pc += 2;
942
                gen_op_movl_A0_im(disp);
943
                rm = 0; /* avoid SS override */
944
                goto no_rm;
945
            } else {
946
                disp = 0;
947
            }
948
            break;
949
        case 1:
950
            disp = (int8_t)ldub(s->pc++);
951
            break;
952
        default:
953
        case 2:
954
            disp = lduw(s->pc);
955
            s->pc += 2;
956
            break;
957
        }
958
        switch(rm) {
959
        case 0:
960
            gen_op_movl_A0_reg[R_EBX]();
961
            gen_op_addl_A0_reg_sN[0][R_ESI]();
962
            break;
963
        case 1:
964
            gen_op_movl_A0_reg[R_EBX]();
965
            gen_op_addl_A0_reg_sN[0][R_EDI]();
966
            break;
967
        case 2:
968
            gen_op_movl_A0_reg[R_EBP]();
969
            gen_op_addl_A0_reg_sN[0][R_ESI]();
970
            break;
971
        case 3:
972
            gen_op_movl_A0_reg[R_EBP]();
973
            gen_op_addl_A0_reg_sN[0][R_EDI]();
974
            break;
975
        case 4:
976
            gen_op_movl_A0_reg[R_ESI]();
977
            break;
978
        case 5:
979
            gen_op_movl_A0_reg[R_EDI]();
980
            break;
981
        case 6:
982
            gen_op_movl_A0_reg[R_EBP]();
983
            break;
984
        default:
985
        case 7:
986
            gen_op_movl_A0_reg[R_EBX]();
987
            break;
988
        }
989
        if (disp != 0)
990
            gen_op_addl_A0_im(disp);
991
        gen_op_andl_A0_ffff();
992
    no_rm:
993
        if (must_add_seg) {
994
            if (override < 0) {
995
                if (rm == 2 || rm == 3 || rm == 6)
996
                    override = R_SS;
997
                else
998
                    override = R_DS;
999
            }
1000
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1001
        }
1002
    }
1003

    
1004
    opreg = OR_A0;
1005
    disp = 0;
1006
    *reg_ptr = opreg;
1007
    *offset_ptr = disp;
1008
}
1009

    
1010
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1011
   OR_TMP0 */
1012
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1013
{
1014
    int mod, rm, opreg, disp;
1015

    
1016
    mod = (modrm >> 6) & 3;
1017
    rm = modrm & 7;
1018
    if (mod == 3) {
1019
        if (is_store) {
1020
            if (reg != OR_TMP0)
1021
                gen_op_mov_TN_reg[ot][0][reg]();
1022
            gen_op_mov_reg_T0[ot][rm]();
1023
        } else {
1024
            gen_op_mov_TN_reg[ot][0][rm]();
1025
            if (reg != OR_TMP0)
1026
                gen_op_mov_reg_T0[ot][reg]();
1027
        }
1028
    } else {
1029
        gen_lea_modrm(s, modrm, &opreg, &disp);
1030
        if (is_store) {
1031
            if (reg != OR_TMP0)
1032
                gen_op_mov_TN_reg[ot][0][reg]();
1033
            gen_op_st_T0_A0[ot]();
1034
        } else {
1035
            gen_op_ld_T0_A0[ot]();
1036
            if (reg != OR_TMP0)
1037
                gen_op_mov_reg_T0[ot][reg]();
1038
        }
1039
    }
1040
}
1041

    
1042
static inline uint32_t insn_get(DisasContext *s, int ot)
1043
{
1044
    uint32_t ret;
1045

    
1046
    switch(ot) {
1047
    case OT_BYTE:
1048
        ret = ldub(s->pc);
1049
        s->pc++;
1050
        break;
1051
    case OT_WORD:
1052
        ret = lduw(s->pc);
1053
        s->pc += 2;
1054
        break;
1055
    default:
1056
    case OT_LONG:
1057
        ret = ldl(s->pc);
1058
        s->pc += 4;
1059
        break;
1060
    }
1061
    return ret;
1062
}
1063

    
1064
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1065
{
1066
    int inv, jcc_op;
1067
    GenOpFunc2 *func;
1068

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

    
1131
static void gen_setcc(DisasContext *s, int b)
1132
{
1133
    int inv, jcc_op;
1134
    GenOpFunc *func;
1135

    
1136
    inv = b & 1;
1137
    jcc_op = (b >> 1) & 7;
1138
    switch(s->cc_op) {
1139
        /* we optimize the cmp/jcc case */
1140
    case CC_OP_SUBB:
1141
    case CC_OP_SUBW:
1142
    case CC_OP_SUBL:
1143
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1144
        if (!func)
1145
            goto slow_jcc;
1146
        break;
1147
        
1148
        /* some jumps are easy to compute */
1149
    case CC_OP_ADDB:
1150
    case CC_OP_ADDW:
1151
    case CC_OP_ADDL:
1152
    case CC_OP_LOGICB:
1153
    case CC_OP_LOGICW:
1154
    case CC_OP_LOGICL:
1155
    case CC_OP_INCB:
1156
    case CC_OP_INCW:
1157
    case CC_OP_INCL:
1158
    case CC_OP_DECB:
1159
    case CC_OP_DECW:
1160
    case CC_OP_DECL:
1161
    case CC_OP_SHLB:
1162
    case CC_OP_SHLW:
1163
    case CC_OP_SHLL:
1164
        switch(jcc_op) {
1165
        case JCC_Z:
1166
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1167
            break;
1168
        case JCC_S:
1169
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1170
            break;
1171
        default:
1172
            goto slow_jcc;
1173
        }
1174
        break;
1175
    default:
1176
    slow_jcc:
1177
        if (s->cc_op != CC_OP_DYNAMIC)
1178
            gen_op_set_cc_op(s->cc_op);
1179
        func = gen_setcc_slow[jcc_op];
1180
        break;
1181
    }
1182
    func();
1183
    if (inv) {
1184
        gen_op_xor_T0_1();
1185
    }
1186
}
1187

    
1188
/* move T0 to seg_reg and compute if the CPU state may change */
1189
static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1190
{
1191
    gen_op_movl_seg_T0(seg_reg);
1192
    if (!s->addseg && seg_reg < R_FS)
1193
        s->is_jmp = 2; /* abort translation because the register may
1194
                          have a non zero base */
1195
}
1196

    
1197
/* generate a push. It depends on ss32, addseg and dflag */
1198
static void gen_push_T0(DisasContext *s)
1199
{
1200
    if (s->ss32) {
1201
        if (!s->addseg) {
1202
            if (s->dflag)
1203
                gen_op_pushl_T0();
1204
            else
1205
                gen_op_pushw_T0();
1206
        } else {
1207
            if (s->dflag)
1208
                gen_op_pushl_ss32_T0();
1209
            else
1210
                gen_op_pushw_ss32_T0();
1211
        }
1212
    } else {
1213
        if (s->dflag)
1214
            gen_op_pushl_ss16_T0();
1215
        else
1216
            gen_op_pushw_ss16_T0();
1217
    }
1218
}
1219

    
1220
/* two step pop is necessary for precise exceptions */
1221
static void gen_pop_T0(DisasContext *s)
1222
{
1223
    if (s->ss32) {
1224
        if (!s->addseg) {
1225
            if (s->dflag)
1226
                gen_op_popl_T0();
1227
            else
1228
                gen_op_popw_T0();
1229
        } else {
1230
            if (s->dflag)
1231
                gen_op_popl_ss32_T0();
1232
            else
1233
                gen_op_popw_ss32_T0();
1234
        }
1235
    } else {
1236
        if (s->dflag)
1237
            gen_op_popl_ss16_T0();
1238
        else
1239
            gen_op_popw_ss16_T0();
1240
    }
1241
}
1242

    
1243
static void gen_pop_update(DisasContext *s)
1244
{
1245
    if (s->ss32) {
1246
        if (s->dflag)
1247
            gen_op_addl_ESP_4();
1248
        else
1249
            gen_op_addl_ESP_2();
1250
    } else {
1251
        if (s->dflag)
1252
            gen_op_addw_ESP_4();
1253
        else
1254
            gen_op_addw_ESP_2();
1255
    }
1256
}
1257

    
1258
/* NOTE: wrap around in 16 bit not fully handled */
1259
static void gen_pusha(DisasContext *s)
1260
{
1261
    int i;
1262
    gen_op_movl_A0_ESP();
1263
    gen_op_addl_A0_im(-16 <<  s->dflag);
1264
    if (!s->ss32)
1265
        gen_op_andl_A0_ffff();
1266
    gen_op_movl_T1_A0();
1267
    if (s->addseg)
1268
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1269
    for(i = 0;i < 8; i++) {
1270
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1271
        gen_op_st_T0_A0[OT_WORD + s->dflag]();
1272
        gen_op_addl_A0_im(2 <<  s->dflag);
1273
    }
1274
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1275
}
1276

    
1277
/* NOTE: wrap around in 16 bit not fully handled */
1278
static void gen_popa(DisasContext *s)
1279
{
1280
    int i;
1281
    gen_op_movl_A0_ESP();
1282
    if (!s->ss32)
1283
        gen_op_andl_A0_ffff();
1284
    gen_op_movl_T1_A0();
1285
    gen_op_addl_T1_im(16 <<  s->dflag);
1286
    if (s->addseg)
1287
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1288
    for(i = 0;i < 8; i++) {
1289
        /* ESP is not reloaded */
1290
        if (i != 3) {
1291
            gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1292
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1293
        }
1294
        gen_op_addl_A0_im(2 <<  s->dflag);
1295
    }
1296
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1297
}
1298

    
1299
/* NOTE: wrap around in 16 bit not fully handled */
1300
/* XXX: check this */
1301
static void gen_enter(DisasContext *s, int esp_addend, int level)
1302
{
1303
    int ot, level1, addend, opsize;
1304

    
1305
    ot = s->dflag + OT_WORD;
1306
    level &= 0x1f;
1307
    level1 = level;
1308
    opsize = 2 << s->dflag;
1309

    
1310
    gen_op_movl_A0_ESP();
1311
    gen_op_addl_A0_im(-opsize);
1312
    if (!s->ss32)
1313
        gen_op_andl_A0_ffff();
1314
    gen_op_movl_T1_A0();
1315
    if (s->addseg)
1316
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1317
    /* push bp */
1318
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1319
    gen_op_st_T0_A0[ot]();
1320
    if (level) {
1321
        while (level--) {
1322
            gen_op_addl_A0_im(-opsize);
1323
            gen_op_addl_T0_im(-opsize);
1324
            gen_op_st_T0_A0[ot]();
1325
        }
1326
        gen_op_addl_A0_im(-opsize);
1327
        /* XXX: add st_T1_A0 ? */
1328
        gen_op_movl_T0_T1();
1329
        gen_op_st_T0_A0[ot]();
1330
    }
1331
    gen_op_mov_reg_T1[ot][R_EBP]();
1332
    addend = -esp_addend;
1333
    if (level1)
1334
        addend -= opsize * (level1 + 1);
1335
    gen_op_addl_T1_im(addend);
1336
    gen_op_mov_reg_T1[ot][R_ESP]();
1337
}
1338

    
1339
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1340
   is set to true if the instruction sets the PC (last instruction of
1341
   a basic block) */
1342
long disas_insn(DisasContext *s, uint8_t *pc_start)
1343
{
1344
    int b, prefixes, aflag, dflag;
1345
    int shift, ot;
1346
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1347
    unsigned int next_eip;
1348

    
1349
    s->pc = pc_start;
1350
    prefixes = 0;
1351
    aflag = s->code32;
1352
    dflag = s->code32;
1353
    s->override = -1;
1354
 next_byte:
1355
    b = ldub(s->pc);
1356
    s->pc++;
1357
    /* check prefixes */
1358
    switch (b) {
1359
    case 0xf3:
1360
        prefixes |= PREFIX_REPZ;
1361
        goto next_byte;
1362
    case 0xf2:
1363
        prefixes |= PREFIX_REPNZ;
1364
        goto next_byte;
1365
    case 0xf0:
1366
        prefixes |= PREFIX_LOCK;
1367
        goto next_byte;
1368
    case 0x2e:
1369
        s->override = R_CS;
1370
        goto next_byte;
1371
    case 0x36:
1372
        s->override = R_SS;
1373
        goto next_byte;
1374
    case 0x3e:
1375
        s->override = R_DS;
1376
        goto next_byte;
1377
    case 0x26:
1378
        s->override = R_ES;
1379
        goto next_byte;
1380
    case 0x64:
1381
        s->override = R_FS;
1382
        goto next_byte;
1383
    case 0x65:
1384
        s->override = R_GS;
1385
        goto next_byte;
1386
    case 0x66:
1387
        prefixes |= PREFIX_DATA;
1388
        goto next_byte;
1389
    case 0x67:
1390
        prefixes |= PREFIX_ADR;
1391
        goto next_byte;
1392
    case 0x9b:
1393
        prefixes |= PREFIX_FWAIT;
1394
        goto next_byte;
1395
    }
1396

    
1397
    if (prefixes & PREFIX_DATA)
1398
        dflag ^= 1;
1399
    if (prefixes & PREFIX_ADR)
1400
        aflag ^= 1;
1401

    
1402
    s->prefix = prefixes;
1403
    s->aflag = aflag;
1404
    s->dflag = dflag;
1405

    
1406
    /* lock generation */
1407
    if (prefixes & PREFIX_LOCK)
1408
        gen_op_lock();
1409

    
1410
    /* now check op code */
1411
 reswitch:
1412
    switch(b) {
1413
    case 0x0f:
1414
        /**************************/
1415
        /* extended op code */
1416
        b = ldub(s->pc++) | 0x100;
1417
        goto reswitch;
1418
        
1419
        /**************************/
1420
        /* arith & logic */
1421
    case 0x00 ... 0x05:
1422
    case 0x08 ... 0x0d:
1423
    case 0x10 ... 0x15:
1424
    case 0x18 ... 0x1d:
1425
    case 0x20 ... 0x25:
1426
    case 0x28 ... 0x2d:
1427
    case 0x30 ... 0x35:
1428
    case 0x38 ... 0x3d:
1429
        {
1430
            int op, f, val;
1431
            op = (b >> 3) & 7;
1432
            f = (b >> 1) & 3;
1433

    
1434
            if ((b & 1) == 0)
1435
                ot = OT_BYTE;
1436
            else
1437
                ot = dflag ? OT_LONG : OT_WORD;
1438
            
1439
            switch(f) {
1440
            case 0: /* OP Ev, Gv */
1441
                modrm = ldub(s->pc++);
1442
                reg = ((modrm >> 3) & 7) + OR_EAX;
1443
                mod = (modrm >> 6) & 3;
1444
                rm = modrm & 7;
1445
                if (mod != 3) {
1446
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1447
                    gen_op_ld_T0_A0[ot]();
1448
                    opreg = OR_TMP0;
1449
                } else {
1450
                    opreg = OR_EAX + rm;
1451
                }
1452
                gen_op(s, op, ot, opreg, reg);
1453
                if (mod != 3 && op != 7) {
1454
                    gen_op_st_T0_A0[ot]();
1455
                }
1456
                break;
1457
            case 1: /* OP Gv, Ev */
1458
                modrm = ldub(s->pc++);
1459
                mod = (modrm >> 6) & 3;
1460
                reg = ((modrm >> 3) & 7) + OR_EAX;
1461
                rm = modrm & 7;
1462
                if (mod != 3) {
1463
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1464
                    gen_op_ld_T1_A0[ot]();
1465
                    opreg = OR_TMP1;
1466
                } else {
1467
                    opreg = OR_EAX + rm;
1468
                }
1469
                gen_op(s, op, ot, reg, opreg);
1470
                break;
1471
            case 2: /* OP A, Iv */
1472
                val = insn_get(s, ot);
1473
                gen_opi(s, op, ot, OR_EAX, val);
1474
                break;
1475
            }
1476
        }
1477
        break;
1478

    
1479
    case 0x80: /* GRP1 */
1480
    case 0x81:
1481
    case 0x83:
1482
        {
1483
            int val;
1484

    
1485
            if ((b & 1) == 0)
1486
                ot = OT_BYTE;
1487
            else
1488
                ot = dflag ? OT_LONG : OT_WORD;
1489
            
1490
            modrm = ldub(s->pc++);
1491
            mod = (modrm >> 6) & 3;
1492
            rm = modrm & 7;
1493
            op = (modrm >> 3) & 7;
1494
            
1495
            if (mod != 3) {
1496
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1497
                gen_op_ld_T0_A0[ot]();
1498
                opreg = OR_TMP0;
1499
            } else {
1500
                opreg = rm + OR_EAX;
1501
            }
1502

    
1503
            switch(b) {
1504
            default:
1505
            case 0x80:
1506
            case 0x81:
1507
                val = insn_get(s, ot);
1508
                break;
1509
            case 0x83:
1510
                val = (int8_t)insn_get(s, OT_BYTE);
1511
                break;
1512
            }
1513

    
1514
            gen_opi(s, op, ot, opreg, val);
1515
            if (op != 7 && mod != 3) {
1516
                gen_op_st_T0_A0[ot]();
1517
            }
1518
        }
1519
        break;
1520

    
1521
        /**************************/
1522
        /* inc, dec, and other misc arith */
1523
    case 0x40 ... 0x47: /* inc Gv */
1524
        ot = dflag ? OT_LONG : OT_WORD;
1525
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1526
        break;
1527
    case 0x48 ... 0x4f: /* dec Gv */
1528
        ot = dflag ? OT_LONG : OT_WORD;
1529
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1530
        break;
1531
    case 0xf6: /* GRP3 */
1532
    case 0xf7:
1533
        if ((b & 1) == 0)
1534
            ot = OT_BYTE;
1535
        else
1536
            ot = dflag ? OT_LONG : OT_WORD;
1537

    
1538
        modrm = ldub(s->pc++);
1539
        mod = (modrm >> 6) & 3;
1540
        rm = modrm & 7;
1541
        op = (modrm >> 3) & 7;
1542
        if (mod != 3) {
1543
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1544
            gen_op_ld_T0_A0[ot]();
1545
        } else {
1546
            gen_op_mov_TN_reg[ot][0][rm]();
1547
        }
1548

    
1549
        switch(op) {
1550
        case 0: /* test */
1551
            val = insn_get(s, ot);
1552
            gen_op_movl_T1_im(val);
1553
            gen_op_testl_T0_T1_cc();
1554
            s->cc_op = CC_OP_LOGICB + ot;
1555
            break;
1556
        case 2: /* not */
1557
            gen_op_notl_T0();
1558
            if (mod != 3) {
1559
                gen_op_st_T0_A0[ot]();
1560
            } else {
1561
                gen_op_mov_reg_T0[ot][rm]();
1562
            }
1563
            break;
1564
        case 3: /* neg */
1565
            gen_op_negl_T0_cc();
1566
            if (mod != 3) {
1567
                gen_op_st_T0_A0[ot]();
1568
            } else {
1569
                gen_op_mov_reg_T0[ot][rm]();
1570
            }
1571
            s->cc_op = CC_OP_SUBB + ot;
1572
            break;
1573
        case 4: /* mul */
1574
            switch(ot) {
1575
            case OT_BYTE:
1576
                gen_op_mulb_AL_T0();
1577
                break;
1578
            case OT_WORD:
1579
                gen_op_mulw_AX_T0();
1580
                break;
1581
            default:
1582
            case OT_LONG:
1583
                gen_op_mull_EAX_T0();
1584
                break;
1585
            }
1586
            s->cc_op = CC_OP_MUL;
1587
            break;
1588
        case 5: /* imul */
1589
            switch(ot) {
1590
            case OT_BYTE:
1591
                gen_op_imulb_AL_T0();
1592
                break;
1593
            case OT_WORD:
1594
                gen_op_imulw_AX_T0();
1595
                break;
1596
            default:
1597
            case OT_LONG:
1598
                gen_op_imull_EAX_T0();
1599
                break;
1600
            }
1601
            s->cc_op = CC_OP_MUL;
1602
            break;
1603
        case 6: /* div */
1604
            switch(ot) {
1605
            case OT_BYTE:
1606
                gen_op_divb_AL_T0();
1607
                break;
1608
            case OT_WORD:
1609
                gen_op_divw_AX_T0();
1610
                break;
1611
            default:
1612
            case OT_LONG:
1613
                gen_op_divl_EAX_T0();
1614
                break;
1615
            }
1616
            break;
1617
        case 7: /* idiv */
1618
            switch(ot) {
1619
            case OT_BYTE:
1620
                gen_op_idivb_AL_T0();
1621
                break;
1622
            case OT_WORD:
1623
                gen_op_idivw_AX_T0();
1624
                break;
1625
            default:
1626
            case OT_LONG:
1627
                gen_op_idivl_EAX_T0();
1628
                break;
1629
            }
1630
            break;
1631
        default:
1632
            goto illegal_op;
1633
        }
1634
        break;
1635

    
1636
    case 0xfe: /* GRP4 */
1637
    case 0xff: /* GRP5 */
1638
        if ((b & 1) == 0)
1639
            ot = OT_BYTE;
1640
        else
1641
            ot = dflag ? OT_LONG : OT_WORD;
1642

    
1643
        modrm = ldub(s->pc++);
1644
        mod = (modrm >> 6) & 3;
1645
        rm = modrm & 7;
1646
        op = (modrm >> 3) & 7;
1647
        if (op >= 2 && b == 0xfe) {
1648
            goto illegal_op;
1649
        }
1650
        if (mod != 3) {
1651
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1652
            if (op != 3 && op != 5)
1653
                gen_op_ld_T0_A0[ot]();
1654
        } else {
1655
            gen_op_mov_TN_reg[ot][0][rm]();
1656
        }
1657

    
1658
        switch(op) {
1659
        case 0: /* inc Ev */
1660
            gen_inc(s, ot, OR_TMP0, 1);
1661
            if (mod != 3)
1662
                gen_op_st_T0_A0[ot]();
1663
            else
1664
                gen_op_mov_reg_T0[ot][rm]();
1665
            break;
1666
        case 1: /* dec Ev */
1667
            gen_inc(s, ot, OR_TMP0, -1);
1668
            if (mod != 3)
1669
                gen_op_st_T0_A0[ot]();
1670
            else
1671
                gen_op_mov_reg_T0[ot][rm]();
1672
            break;
1673
        case 2: /* call Ev */
1674
            /* XXX: optimize if memory (no and is necessary) */
1675
            if (s->dflag == 0)
1676
                gen_op_andl_T0_ffff();
1677
            gen_op_jmp_T0();
1678
            next_eip = s->pc - s->cs_base;
1679
            gen_op_movl_T0_im(next_eip);
1680
            gen_push_T0(s);
1681
            s->is_jmp = 1;
1682
            break;
1683
        case 3: /* lcall Ev */
1684
            /* push return segment + offset */
1685
            gen_op_movl_T0_seg(R_CS);
1686
            gen_push_T0(s);
1687
            next_eip = s->pc - s->cs_base;
1688
            gen_op_movl_T0_im(next_eip);
1689
            gen_push_T0(s);
1690

    
1691
            gen_op_ld_T1_A0[ot]();
1692
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1693
            gen_op_lduw_T0_A0();
1694
            gen_movl_seg_T0(s, R_CS);
1695
            gen_op_movl_T0_T1();
1696
            gen_op_jmp_T0();
1697
            s->is_jmp = 1;
1698
            break;
1699
        case 4: /* jmp Ev */
1700
            if (s->dflag == 0)
1701
                gen_op_andl_T0_ffff();
1702
            gen_op_jmp_T0();
1703
            s->is_jmp = 1;
1704
            break;
1705
        case 5: /* ljmp Ev */
1706
            gen_op_ld_T1_A0[ot]();
1707
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1708
            gen_op_lduw_T0_A0();
1709
            gen_movl_seg_T0(s, R_CS);
1710
            gen_op_movl_T0_T1();
1711
            gen_op_jmp_T0();
1712
            s->is_jmp = 1;
1713
            break;
1714
        case 6: /* push Ev */
1715
            gen_push_T0(s);
1716
            break;
1717
        default:
1718
            goto illegal_op;
1719
        }
1720
        break;
1721

    
1722
    case 0x84: /* test Ev, Gv */
1723
    case 0x85: 
1724
        if ((b & 1) == 0)
1725
            ot = OT_BYTE;
1726
        else
1727
            ot = dflag ? OT_LONG : OT_WORD;
1728

    
1729
        modrm = ldub(s->pc++);
1730
        mod = (modrm >> 6) & 3;
1731
        rm = modrm & 7;
1732
        reg = (modrm >> 3) & 7;
1733
        
1734
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1735
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1736
        gen_op_testl_T0_T1_cc();
1737
        s->cc_op = CC_OP_LOGICB + ot;
1738
        break;
1739
        
1740
    case 0xa8: /* test eAX, Iv */
1741
    case 0xa9:
1742
        if ((b & 1) == 0)
1743
            ot = OT_BYTE;
1744
        else
1745
            ot = dflag ? OT_LONG : OT_WORD;
1746
        val = insn_get(s, ot);
1747

    
1748
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1749
        gen_op_movl_T1_im(val);
1750
        gen_op_testl_T0_T1_cc();
1751
        s->cc_op = CC_OP_LOGICB + ot;
1752
        break;
1753
        
1754
    case 0x98: /* CWDE/CBW */
1755
        if (dflag)
1756
            gen_op_movswl_EAX_AX();
1757
        else
1758
            gen_op_movsbw_AX_AL();
1759
        break;
1760
    case 0x99: /* CDQ/CWD */
1761
        if (dflag)
1762
            gen_op_movslq_EDX_EAX();
1763
        else
1764
            gen_op_movswl_DX_AX();
1765
        break;
1766
    case 0x1af: /* imul Gv, Ev */
1767
    case 0x69: /* imul Gv, Ev, I */
1768
    case 0x6b:
1769
        ot = dflag ? OT_LONG : OT_WORD;
1770
        modrm = ldub(s->pc++);
1771
        reg = ((modrm >> 3) & 7) + OR_EAX;
1772
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1773
        if (b == 0x69) {
1774
            val = insn_get(s, ot);
1775
            gen_op_movl_T1_im(val);
1776
        } else if (b == 0x6b) {
1777
            val = insn_get(s, OT_BYTE);
1778
            gen_op_movl_T1_im(val);
1779
        } else {
1780
            gen_op_mov_TN_reg[ot][1][reg]();
1781
        }
1782

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

    
1936
        /**************************/
1937
        /* mov */
1938
    case 0x88:
1939
    case 0x89: /* mov Gv, Ev */
1940
        if ((b & 1) == 0)
1941
            ot = OT_BYTE;
1942
        else
1943
            ot = dflag ? OT_LONG : OT_WORD;
1944
        modrm = ldub(s->pc++);
1945
        reg = (modrm >> 3) & 7;
1946
        
1947
        /* generate a generic store */
1948
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1949
        break;
1950
    case 0xc6:
1951
    case 0xc7: /* mov Ev, Iv */
1952
        if ((b & 1) == 0)
1953
            ot = OT_BYTE;
1954
        else
1955
            ot = dflag ? OT_LONG : OT_WORD;
1956
        modrm = ldub(s->pc++);
1957
        mod = (modrm >> 6) & 3;
1958
        if (mod != 3)
1959
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1960
        val = insn_get(s, ot);
1961
        gen_op_movl_T0_im(val);
1962
        if (mod != 3)
1963
            gen_op_st_T0_A0[ot]();
1964
        else
1965
            gen_op_mov_reg_T0[ot][modrm & 7]();
1966
        break;
1967
    case 0x8a:
1968
    case 0x8b: /* mov Ev, Gv */
1969
        if ((b & 1) == 0)
1970
            ot = OT_BYTE;
1971
        else
1972
            ot = dflag ? OT_LONG : OT_WORD;
1973
        modrm = ldub(s->pc++);
1974
        reg = (modrm >> 3) & 7;
1975
        
1976
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1977
        gen_op_mov_reg_T0[ot][reg]();
1978
        break;
1979
    case 0x8e: /* mov seg, Gv */
1980
        ot = dflag ? OT_LONG : OT_WORD;
1981
        modrm = ldub(s->pc++);
1982
        reg = (modrm >> 3) & 7;
1983
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1984
        if (reg >= 6 || reg == R_CS)
1985
            goto illegal_op;
1986
        gen_movl_seg_T0(s, reg);
1987
        break;
1988
    case 0x8c: /* mov Gv, seg */
1989
        ot = dflag ? OT_LONG : OT_WORD;
1990
        modrm = ldub(s->pc++);
1991
        reg = (modrm >> 3) & 7;
1992
        if (reg >= 6)
1993
            goto illegal_op;
1994
        gen_op_movl_T0_seg(reg);
1995
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1996
        break;
1997

    
1998
    case 0x1b6: /* movzbS Gv, Eb */
1999
    case 0x1b7: /* movzwS Gv, Eb */
2000
    case 0x1be: /* movsbS Gv, Eb */
2001
    case 0x1bf: /* movswS Gv, Eb */
2002
        {
2003
            int d_ot;
2004
            /* d_ot is the size of destination */
2005
            d_ot = dflag + OT_WORD;
2006
            /* ot is the size of source */
2007
            ot = (b & 1) + OT_BYTE;
2008
            modrm = ldub(s->pc++);
2009
            reg = ((modrm >> 3) & 7) + OR_EAX;
2010
            mod = (modrm >> 6) & 3;
2011
            rm = modrm & 7;
2012
            
2013
            if (mod == 3) {
2014
                gen_op_mov_TN_reg[ot][0][rm]();
2015
                switch(ot | (b & 8)) {
2016
                case OT_BYTE:
2017
                    gen_op_movzbl_T0_T0();
2018
                    break;
2019
                case OT_BYTE | 8:
2020
                    gen_op_movsbl_T0_T0();
2021
                    break;
2022
                case OT_WORD:
2023
                    gen_op_movzwl_T0_T0();
2024
                    break;
2025
                default:
2026
                case OT_WORD | 8:
2027
                    gen_op_movswl_T0_T0();
2028
                    break;
2029
                }
2030
                gen_op_mov_reg_T0[d_ot][reg]();
2031
            } else {
2032
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2033
                if (b & 8) {
2034
                    gen_op_lds_T0_A0[ot]();
2035
                } else {
2036
                    gen_op_ldu_T0_A0[ot]();
2037
                }
2038
                gen_op_mov_reg_T0[d_ot][reg]();
2039
            }
2040
        }
2041
        break;
2042

    
2043
    case 0x8d: /* lea */
2044
        ot = dflag ? OT_LONG : OT_WORD;
2045
        modrm = ldub(s->pc++);
2046
        reg = (modrm >> 3) & 7;
2047
        /* we must ensure that no segment is added */
2048
        s->override = -1;
2049
        val = s->addseg;
2050
        s->addseg = 0;
2051
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2052
        s->addseg = val;
2053
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2054
        break;
2055
        
2056
    case 0xa0: /* mov EAX, Ov */
2057
    case 0xa1:
2058
    case 0xa2: /* mov Ov, EAX */
2059
    case 0xa3:
2060
        if ((b & 1) == 0)
2061
            ot = OT_BYTE;
2062
        else
2063
            ot = dflag ? OT_LONG : OT_WORD;
2064
        if (s->aflag)
2065
            offset_addr = insn_get(s, OT_LONG);
2066
        else
2067
            offset_addr = insn_get(s, OT_WORD);
2068
        gen_op_movl_A0_im(offset_addr);
2069
        /* handle override */
2070
        {
2071
            int override, must_add_seg;
2072
            must_add_seg = s->addseg;
2073
            if (s->override >= 0) {
2074
                override = s->override;
2075
                must_add_seg = 1;
2076
            } else {
2077
                override = R_DS;
2078
            }
2079
            if (must_add_seg) {
2080
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2081
            }
2082
        }
2083
        if ((b & 2) == 0) {
2084
            gen_op_ld_T0_A0[ot]();
2085
            gen_op_mov_reg_T0[ot][R_EAX]();
2086
        } else {
2087
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2088
            gen_op_st_T0_A0[ot]();
2089
        }
2090
        break;
2091
    case 0xd7: /* xlat */
2092
        gen_op_movl_A0_reg[R_EBX]();
2093
        gen_op_addl_A0_AL();
2094
        if (s->aflag == 0)
2095
            gen_op_andl_A0_ffff();
2096
        /* handle override */
2097
        {
2098
            int override, must_add_seg;
2099
            must_add_seg = s->addseg;
2100
            override = R_DS;
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
        gen_op_ldub_T0_A0();
2112
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2113
        break;
2114
    case 0xb0 ... 0xb7: /* mov R, Ib */
2115
        val = insn_get(s, OT_BYTE);
2116
        gen_op_movl_T0_im(val);
2117
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2118
        break;
2119
    case 0xb8 ... 0xbf: /* mov R, Iv */
2120
        ot = dflag ? OT_LONG : OT_WORD;
2121
        val = insn_get(s, ot);
2122
        reg = OR_EAX + (b & 7);
2123
        gen_op_movl_T0_im(val);
2124
        gen_op_mov_reg_T0[ot][reg]();
2125
        break;
2126

    
2127
    case 0x91 ... 0x97: /* xchg R, EAX */
2128
        ot = dflag ? OT_LONG : OT_WORD;
2129
        reg = b & 7;
2130
        rm = R_EAX;
2131
        goto do_xchg_reg;
2132
    case 0x86:
2133
    case 0x87: /* xchg Ev, Gv */
2134
        if ((b & 1) == 0)
2135
            ot = OT_BYTE;
2136
        else
2137
            ot = dflag ? OT_LONG : OT_WORD;
2138
        modrm = ldub(s->pc++);
2139
        reg = (modrm >> 3) & 7;
2140
        mod = (modrm >> 6) & 3;
2141
        if (mod == 3) {
2142
            rm = modrm & 7;
2143
        do_xchg_reg:
2144
            gen_op_mov_TN_reg[ot][0][reg]();
2145
            gen_op_mov_TN_reg[ot][1][rm]();
2146
            gen_op_mov_reg_T0[ot][rm]();
2147
            gen_op_mov_reg_T1[ot][reg]();
2148
        } else {
2149
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2150
            gen_op_mov_TN_reg[ot][0][reg]();
2151
            /* for xchg, lock is implicit */
2152
            if (!(prefixes & PREFIX_LOCK))
2153
                gen_op_lock();
2154
            gen_op_ld_T1_A0[ot]();
2155
            gen_op_st_T0_A0[ot]();
2156
            if (!(prefixes & PREFIX_LOCK))
2157
                gen_op_unlock();
2158
            gen_op_mov_reg_T1[ot][reg]();
2159
        }
2160
        break;
2161
    case 0xc4: /* les Gv */
2162
        op = R_ES;
2163
        goto do_lxx;
2164
    case 0xc5: /* lds Gv */
2165
        op = R_DS;
2166
        goto do_lxx;
2167
    case 0x1b2: /* lss Gv */
2168
        op = R_SS;
2169
        goto do_lxx;
2170
    case 0x1b4: /* lfs Gv */
2171
        op = R_FS;
2172
        goto do_lxx;
2173
    case 0x1b5: /* lgs Gv */
2174
        op = R_GS;
2175
    do_lxx:
2176
        ot = dflag ? OT_LONG : OT_WORD;
2177
        modrm = ldub(s->pc++);
2178
        reg = (modrm >> 3) & 7;
2179
        mod = (modrm >> 6) & 3;
2180
        if (mod == 3)
2181
            goto illegal_op;
2182
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2183
        gen_op_ld_T1_A0[ot]();
2184
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2185
        /* load the segment first to handle exceptions properly */
2186
        gen_op_lduw_T0_A0();
2187
        gen_movl_seg_T0(s, op);
2188
        /* then put the data */
2189
        gen_op_mov_reg_T1[ot][reg]();
2190
        break;
2191
        
2192
        /************************/
2193
        /* shifts */
2194
    case 0xc0:
2195
    case 0xc1:
2196
        /* shift Ev,Ib */
2197
        shift = 2;
2198
    grp2:
2199
        {
2200
            if ((b & 1) == 0)
2201
                ot = OT_BYTE;
2202
            else
2203
                ot = dflag ? OT_LONG : OT_WORD;
2204
            
2205
            modrm = ldub(s->pc++);
2206
            mod = (modrm >> 6) & 3;
2207
            rm = modrm & 7;
2208
            op = (modrm >> 3) & 7;
2209
            
2210
            if (mod != 3) {
2211
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2212
                gen_op_ld_T0_A0[ot]();
2213
                opreg = OR_TMP0;
2214
            } else {
2215
                opreg = rm + OR_EAX;
2216
            }
2217

    
2218
            /* simpler op */
2219
            if (shift == 0) {
2220
                gen_shift(s, op, ot, opreg, OR_ECX);
2221
            } else {
2222
                if (shift == 2) {
2223
                    shift = ldub(s->pc++);
2224
                }
2225
                gen_shifti(s, op, ot, opreg, shift);
2226
            }
2227

    
2228
            if (mod != 3) {
2229
                gen_op_st_T0_A0[ot]();
2230
            }
2231
        }
2232
        break;
2233
    case 0xd0:
2234
    case 0xd1:
2235
        /* shift Ev,1 */
2236
        shift = 1;
2237
        goto grp2;
2238
    case 0xd2:
2239
    case 0xd3:
2240
        /* shift Ev,cl */
2241
        shift = 0;
2242
        goto grp2;
2243

    
2244
    case 0x1a4: /* shld imm */
2245
        op = 0;
2246
        shift = 1;
2247
        goto do_shiftd;
2248
    case 0x1a5: /* shld cl */
2249
        op = 0;
2250
        shift = 0;
2251
        goto do_shiftd;
2252
    case 0x1ac: /* shrd imm */
2253
        op = 1;
2254
        shift = 1;
2255
        goto do_shiftd;
2256
    case 0x1ad: /* shrd cl */
2257
        op = 1;
2258
        shift = 0;
2259
    do_shiftd:
2260
        ot = dflag ? OT_LONG : OT_WORD;
2261
        modrm = ldub(s->pc++);
2262
        mod = (modrm >> 6) & 3;
2263
        rm = modrm & 7;
2264
        reg = (modrm >> 3) & 7;
2265
        
2266
        if (mod != 3) {
2267
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2268
            gen_op_ld_T0_A0[ot]();
2269
        } else {
2270
            gen_op_mov_TN_reg[ot][0][rm]();
2271
        }
2272
        gen_op_mov_TN_reg[ot][1][reg]();
2273
        
2274
        if (shift) {
2275
            val = ldub(s->pc++);
2276
            val &= 0x1f;
2277
            if (val) {
2278
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2279
                if (op == 0 && ot != OT_WORD)
2280
                    s->cc_op = CC_OP_SHLB + ot;
2281
                else
2282
                    s->cc_op = CC_OP_SARB + ot;
2283
            }
2284
        } else {
2285
            if (s->cc_op != CC_OP_DYNAMIC)
2286
                gen_op_set_cc_op(s->cc_op);
2287
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2288
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2289
        }
2290
        if (mod != 3) {
2291
            gen_op_st_T0_A0[ot]();
2292
        } else {
2293
            gen_op_mov_reg_T0[ot][rm]();
2294
        }
2295
        break;
2296

    
2297
        /************************/
2298
        /* floats */
2299
    case 0xd8 ... 0xdf: 
2300
        modrm = ldub(s->pc++);
2301
        mod = (modrm >> 6) & 3;
2302
        rm = modrm & 7;
2303
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2304
        
2305
        if (mod != 3) {
2306
            /* memory op */
2307
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2308
            switch(op) {
2309
            case 0x00 ... 0x07: /* fxxxs */
2310
            case 0x10 ... 0x17: /* fixxxl */
2311
            case 0x20 ... 0x27: /* fxxxl */
2312
            case 0x30 ... 0x37: /* fixxx */
2313
                {
2314
                    int op1;
2315
                    op1 = op & 7;
2316

    
2317
                    switch(op >> 4) {
2318
                    case 0:
2319
                        gen_op_flds_FT0_A0();
2320
                        break;
2321
                    case 1:
2322
                        gen_op_fildl_FT0_A0();
2323
                        break;
2324
                    case 2:
2325
                        gen_op_fldl_FT0_A0();
2326
                        break;
2327
                    case 3:
2328
                    default:
2329
                        gen_op_fild_FT0_A0();
2330
                        break;
2331
                    }
2332
                    
2333
                    gen_op_fp_arith_ST0_FT0[op1]();
2334
                    if (op1 == 3) {
2335
                        /* fcomp needs pop */
2336
                        gen_op_fpop();
2337
                    }
2338
                }
2339
                break;
2340
            case 0x08: /* flds */
2341
            case 0x0a: /* fsts */
2342
            case 0x0b: /* fstps */
2343
            case 0x18: /* fildl */
2344
            case 0x1a: /* fistl */
2345
            case 0x1b: /* fistpl */
2346
            case 0x28: /* fldl */
2347
            case 0x2a: /* fstl */
2348
            case 0x2b: /* fstpl */
2349
            case 0x38: /* filds */
2350
            case 0x3a: /* fists */
2351
            case 0x3b: /* fistps */
2352
                
2353
                switch(op & 7) {
2354
                case 0:
2355
                    gen_op_fpush();
2356
                    switch(op >> 4) {
2357
                    case 0:
2358
                        gen_op_flds_ST0_A0();
2359
                        break;
2360
                    case 1:
2361
                        gen_op_fildl_ST0_A0();
2362
                        break;
2363
                    case 2:
2364
                        gen_op_fldl_ST0_A0();
2365
                        break;
2366
                    case 3:
2367
                    default:
2368
                        gen_op_fild_ST0_A0();
2369
                        break;
2370
                    }
2371
                    break;
2372
                default:
2373
                    switch(op >> 4) {
2374
                    case 0:
2375
                        gen_op_fsts_ST0_A0();
2376
                        break;
2377
                    case 1:
2378
                        gen_op_fistl_ST0_A0();
2379
                        break;
2380
                    case 2:
2381
                        gen_op_fstl_ST0_A0();
2382
                        break;
2383
                    case 3:
2384
                    default:
2385
                        gen_op_fist_ST0_A0();
2386
                        break;
2387
                    }
2388
                    if ((op & 7) == 3)
2389
                        gen_op_fpop();
2390
                    break;
2391
                }
2392
                break;
2393
            case 0x0d: /* fldcw mem */
2394
                gen_op_fldcw_A0();
2395
                break;
2396
            case 0x0f: /* fnstcw mem */
2397
                gen_op_fnstcw_A0();
2398
                break;
2399
            case 0x1d: /* fldt mem */
2400
                gen_op_fpush();
2401
                gen_op_fldt_ST0_A0();
2402
                break;
2403
            case 0x1f: /* fstpt mem */
2404
                gen_op_fstt_ST0_A0();
2405
                gen_op_fpop();
2406
                break;
2407
            case 0x2f: /* fnstsw mem */
2408
                gen_op_fnstsw_A0();
2409
                break;
2410
            case 0x3c: /* fbld */
2411
                gen_op_fpush();
2412
                gen_op_fbld_ST0_A0();
2413
                break;
2414
            case 0x3e: /* fbstp */
2415
                gen_op_fbst_ST0_A0();
2416
                gen_op_fpop();
2417
                break;
2418
            case 0x3d: /* fildll */
2419
                gen_op_fpush();
2420
                gen_op_fildll_ST0_A0();
2421
                break;
2422
            case 0x3f: /* fistpll */
2423
                gen_op_fistll_ST0_A0();
2424
                gen_op_fpop();
2425
                break;
2426
            default:
2427
                goto illegal_op;
2428
            }
2429
        } else {
2430
            /* register float ops */
2431
            opreg = rm;
2432

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

    
2657
    case 0xa4: /* movsS */
2658
    case 0xa5:
2659
        if ((b & 1) == 0)
2660
            ot = OT_BYTE;
2661
        else
2662
            ot = dflag ? OT_LONG : OT_WORD;
2663

    
2664
        if (prefixes & PREFIX_REPZ) {
2665
            gen_string_ds(s, ot, gen_op_movs + 9);
2666
        } else {
2667
            gen_string_ds(s, ot, gen_op_movs);
2668
        }
2669
        break;
2670
        
2671
    case 0xaa: /* stosS */
2672
    case 0xab:
2673
        if ((b & 1) == 0)
2674
            ot = OT_BYTE;
2675
        else
2676
            ot = dflag ? OT_LONG : OT_WORD;
2677

    
2678
        if (prefixes & PREFIX_REPZ) {
2679
            gen_string_es(s, ot, gen_op_stos + 9);
2680
        } else {
2681
            gen_string_es(s, ot, gen_op_stos);
2682
        }
2683
        break;
2684
    case 0xac: /* lodsS */
2685
    case 0xad:
2686
        if ((b & 1) == 0)
2687
            ot = OT_BYTE;
2688
        else
2689
            ot = dflag ? OT_LONG : OT_WORD;
2690
        if (prefixes & PREFIX_REPZ) {
2691
            gen_string_ds(s, ot, gen_op_lods + 9);
2692
        } else {
2693
            gen_string_ds(s, ot, gen_op_lods);
2694
        }
2695
        break;
2696
    case 0xae: /* scasS */
2697
    case 0xaf:
2698
        if ((b & 1) == 0)
2699
            ot = OT_BYTE;
2700
        else
2701
                ot = dflag ? OT_LONG : OT_WORD;
2702
        if (prefixes & PREFIX_REPNZ) {
2703
            if (s->cc_op != CC_OP_DYNAMIC)
2704
                gen_op_set_cc_op(s->cc_op);
2705
            gen_string_es(s, ot, gen_op_scas + 9 * 2);
2706
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2707
        } else if (prefixes & PREFIX_REPZ) {
2708
            if (s->cc_op != CC_OP_DYNAMIC)
2709
                gen_op_set_cc_op(s->cc_op);
2710
            gen_string_es(s, ot, gen_op_scas + 9);
2711
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2712
        } else {
2713
            gen_string_es(s, ot, gen_op_scas);
2714
            s->cc_op = CC_OP_SUBB + ot;
2715
        }
2716
        break;
2717

    
2718
    case 0xa6: /* cmpsS */
2719
    case 0xa7:
2720
        if ((b & 1) == 0)
2721
            ot = OT_BYTE;
2722
        else
2723
            ot = dflag ? OT_LONG : OT_WORD;
2724
        if (prefixes & PREFIX_REPNZ) {
2725
            if (s->cc_op != CC_OP_DYNAMIC)
2726
                gen_op_set_cc_op(s->cc_op);
2727
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2728
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2729
        } else if (prefixes & PREFIX_REPZ) {
2730
            if (s->cc_op != CC_OP_DYNAMIC)
2731
                gen_op_set_cc_op(s->cc_op);
2732
            gen_string_ds(s, ot, gen_op_cmps + 9);
2733
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2734
        } else {
2735
            gen_string_ds(s, ot, gen_op_cmps);
2736
            s->cc_op = CC_OP_SUBB + ot;
2737
        }
2738
        break;
2739
    case 0x6c: /* insS */
2740
    case 0x6d:
2741
        if ((b & 1) == 0)
2742
            ot = OT_BYTE;
2743
        else
2744
            ot = dflag ? OT_LONG : OT_WORD;
2745
        if (prefixes & PREFIX_REPZ) {
2746
            gen_string_es(s, ot, gen_op_ins + 9);
2747
        } else {
2748
            gen_string_es(s, ot, gen_op_ins);
2749
        }
2750
        break;
2751
    case 0x6e: /* outsS */
2752
    case 0x6f:
2753
        if ((b & 1) == 0)
2754
            ot = OT_BYTE;
2755
        else
2756
            ot = dflag ? OT_LONG : OT_WORD;
2757
        if (prefixes & PREFIX_REPZ) {
2758
            gen_string_ds(s, ot, gen_op_outs + 9);
2759
        } else {
2760
            gen_string_ds(s, ot, gen_op_outs);
2761
        }
2762
        break;
2763

    
2764
        /************************/
2765
        /* port I/O */
2766
    case 0xe4:
2767
    case 0xe5:
2768
        if ((b & 1) == 0)
2769
            ot = OT_BYTE;
2770
        else
2771
            ot = dflag ? OT_LONG : OT_WORD;
2772
        val = ldub(s->pc++);
2773
        gen_op_movl_T0_im(val);
2774
        gen_op_in[ot]();
2775
        gen_op_mov_reg_T1[ot][R_EAX]();
2776
        break;
2777
    case 0xe6:
2778
    case 0xe7:
2779
        if ((b & 1) == 0)
2780
            ot = OT_BYTE;
2781
        else
2782
            ot = dflag ? OT_LONG : OT_WORD;
2783
        val = ldub(s->pc++);
2784
        gen_op_movl_T0_im(val);
2785
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2786
        gen_op_out[ot]();
2787
        break;
2788
    case 0xec:
2789
    case 0xed:
2790
        if ((b & 1) == 0)
2791
            ot = OT_BYTE;
2792
        else
2793
            ot = dflag ? OT_LONG : OT_WORD;
2794
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2795
        gen_op_in[ot]();
2796
        gen_op_mov_reg_T1[ot][R_EAX]();
2797
        break;
2798
    case 0xee:
2799
    case 0xef:
2800
        if ((b & 1) == 0)
2801
            ot = OT_BYTE;
2802
        else
2803
            ot = dflag ? OT_LONG : OT_WORD;
2804
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2805
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2806
        gen_op_out[ot]();
2807
        break;
2808

    
2809
        /************************/
2810
        /* control */
2811
    case 0xc2: /* ret im */
2812
        val = ldsw(s->pc);
2813
        s->pc += 2;
2814
        gen_pop_T0(s);
2815
        if (s->ss32)
2816
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2817
        else
2818
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2819
        if (s->dflag == 0)
2820
            gen_op_andl_T0_ffff();
2821
        gen_op_jmp_T0();
2822
        s->is_jmp = 1;
2823
        break;
2824
    case 0xc3: /* ret */
2825
        gen_pop_T0(s);
2826
        gen_pop_update(s);
2827
        if (s->dflag == 0)
2828
            gen_op_andl_T0_ffff();
2829
        gen_op_jmp_T0();
2830
        s->is_jmp = 1;
2831
        break;
2832
    case 0xca: /* lret im */
2833
        /* XXX: not restartable */
2834
        val = ldsw(s->pc);
2835
        s->pc += 2;
2836
        /* pop offset */
2837
        gen_pop_T0(s);
2838
        if (s->dflag == 0)
2839
            gen_op_andl_T0_ffff();
2840
        gen_op_jmp_T0();
2841
        gen_pop_update(s);
2842
        /* pop selector */
2843
        gen_pop_T0(s);
2844
        gen_movl_seg_T0(s, R_CS);
2845
        gen_pop_update(s);
2846
        /* add stack offset */
2847
        if (s->ss32)
2848
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2849
        else
2850
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2851
        s->is_jmp = 1;
2852
        break;
2853
    case 0xcb: /* lret */
2854
        /* XXX: not restartable */
2855
        /* pop offset */
2856
        gen_pop_T0(s);
2857
        if (s->dflag == 0)
2858
            gen_op_andl_T0_ffff();
2859
        gen_op_jmp_T0();
2860
        gen_pop_update(s);
2861
        /* pop selector */
2862
        gen_pop_T0(s);
2863
        gen_movl_seg_T0(s, R_CS);
2864
        gen_pop_update(s);
2865
        s->is_jmp = 1;
2866
        break;
2867
    case 0xcf: /* iret */
2868
        /* XXX: not restartable */
2869
        /* pop offset */
2870
        gen_pop_T0(s);
2871
        if (s->dflag == 0)
2872
            gen_op_andl_T0_ffff();
2873
        gen_op_jmp_T0();
2874
        gen_pop_update(s);
2875
        /* pop selector */
2876
        gen_pop_T0(s);
2877
        gen_movl_seg_T0(s, R_CS);
2878
        gen_pop_update(s);
2879
        /* pop eflags */
2880
        gen_pop_T0(s);
2881
        if (s->dflag) {
2882
            if (s->vm86)
2883
                gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
2884
            else
2885
                gen_op_movl_eflags_T0();
2886
        } else {
2887
            if (s->vm86)
2888
                gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
2889
            else
2890
                gen_op_movw_eflags_T0();
2891
        }
2892
        gen_pop_update(s);
2893
        s->cc_op = CC_OP_EFLAGS;
2894
        s->is_jmp = 1;
2895
        break;
2896
    case 0xe8: /* call im */
2897
        {
2898
            unsigned int next_eip;
2899
            ot = dflag ? OT_LONG : OT_WORD;
2900
            val = insn_get(s, ot);
2901
            next_eip = s->pc - s->cs_base;
2902
            val += next_eip;
2903
            if (s->dflag == 0)
2904
                val &= 0xffff;
2905
            gen_op_movl_T0_im(next_eip);
2906
            gen_push_T0(s);
2907
            gen_op_jmp_im(val);
2908
            s->is_jmp = 1;
2909
        }
2910
        break;
2911
    case 0x9a: /* lcall im */
2912
        {
2913
            unsigned int selector, offset;
2914

    
2915
            ot = dflag ? OT_LONG : OT_WORD;
2916
            offset = insn_get(s, ot);
2917
            selector = insn_get(s, OT_WORD);
2918
            
2919
            /* push return segment + offset */
2920
            gen_op_movl_T0_seg(R_CS);
2921
            gen_push_T0(s);
2922
            next_eip = s->pc - s->cs_base;
2923
            gen_op_movl_T0_im(next_eip);
2924
            gen_push_T0(s);
2925

    
2926
            /* change cs and pc */
2927
            gen_op_movl_T0_im(selector);
2928
            gen_movl_seg_T0(s, R_CS);
2929
            gen_op_jmp_im((unsigned long)offset);
2930
            s->is_jmp = 1;
2931
        }
2932
        break;
2933
    case 0xe9: /* jmp */
2934
        ot = dflag ? OT_LONG : OT_WORD;
2935
        val = insn_get(s, ot);
2936
        val += s->pc - s->cs_base;
2937
        if (s->dflag == 0)
2938
            val = val & 0xffff;
2939
        gen_op_jmp_im(val);
2940
        s->is_jmp = 1;
2941
        break;
2942
    case 0xea: /* ljmp im */
2943
        {
2944
            unsigned int selector, offset;
2945

    
2946
            ot = dflag ? OT_LONG : OT_WORD;
2947
            offset = insn_get(s, ot);
2948
            selector = insn_get(s, OT_WORD);
2949
            
2950
            /* change cs and pc */
2951
            gen_op_movl_T0_im(selector);
2952
            gen_movl_seg_T0(s, R_CS);
2953
            gen_op_jmp_im((unsigned long)offset);
2954
            s->is_jmp = 1;
2955
        }
2956
        break;
2957
    case 0xeb: /* jmp Jb */
2958
        val = (int8_t)insn_get(s, OT_BYTE);
2959
        val += s->pc - s->cs_base;
2960
        if (s->dflag == 0)
2961
            val = val & 0xffff;
2962
        gen_op_jmp_im(val);
2963
        s->is_jmp = 1;
2964
        break;
2965
    case 0x70 ... 0x7f: /* jcc Jb */
2966
        val = (int8_t)insn_get(s, OT_BYTE);
2967
        goto do_jcc;
2968
    case 0x180 ... 0x18f: /* jcc Jv */
2969
        if (dflag) {
2970
            val = insn_get(s, OT_LONG);
2971
        } else {
2972
            val = (int16_t)insn_get(s, OT_WORD); 
2973
        }
2974
    do_jcc:
2975
        next_eip = s->pc - s->cs_base;
2976
        val += next_eip;
2977
        if (s->dflag == 0)
2978
            val &= 0xffff;
2979
        gen_jcc(s, b, val, next_eip);
2980
        s->is_jmp = 1;
2981
        break;
2982

    
2983
    case 0x190 ... 0x19f: /* setcc Gv */
2984
        modrm = ldub(s->pc++);
2985
        gen_setcc(s, b);
2986
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2987
        break;
2988
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
2989
        ot = dflag ? OT_LONG : OT_WORD;
2990
        modrm = ldub(s->pc++);
2991
        reg = (modrm >> 3) & 7;
2992
        mod = (modrm >> 6) & 3;
2993
        gen_setcc(s, b);
2994
        if (mod != 3) {
2995
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2996
            gen_op_ld_T1_A0[ot]();
2997
        } else {
2998
            rm = modrm & 7;
2999
            gen_op_mov_TN_reg[ot][1][rm]();
3000
        }
3001
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3002
        break;
3003
        
3004
        /************************/
3005
        /* flags */
3006
    case 0x9c: /* pushf */
3007
        if (s->cc_op != CC_OP_DYNAMIC)
3008
            gen_op_set_cc_op(s->cc_op);
3009
        if (s->vm86)
3010
            gen_op_movl_T0_eflags_vm();
3011
        else
3012
            gen_op_movl_T0_eflags();
3013
        gen_push_T0(s);
3014
        break;
3015
    case 0x9d: /* popf */
3016
        gen_pop_T0(s);
3017
        if (s->dflag) {
3018
            if (s->vm86)
3019
                gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
3020
            else
3021
                gen_op_movl_eflags_T0();
3022
        } else {
3023
            if (s->vm86)
3024
                gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
3025
            else
3026
                gen_op_movw_eflags_T0();
3027
        }
3028
        gen_pop_update(s);
3029
        s->cc_op = CC_OP_EFLAGS;
3030
        break;
3031
    case 0x9e: /* sahf */
3032
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3033
        if (s->cc_op != CC_OP_DYNAMIC)
3034
            gen_op_set_cc_op(s->cc_op);
3035
        gen_op_movb_eflags_T0();
3036
        s->cc_op = CC_OP_EFLAGS;
3037
        break;
3038
    case 0x9f: /* lahf */
3039
        if (s->cc_op != CC_OP_DYNAMIC)
3040
            gen_op_set_cc_op(s->cc_op);
3041
        gen_op_movl_T0_eflags();
3042
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3043
        break;
3044
    case 0xf5: /* cmc */
3045
        if (s->cc_op != CC_OP_DYNAMIC)
3046
            gen_op_set_cc_op(s->cc_op);
3047
        gen_op_cmc();
3048
        s->cc_op = CC_OP_EFLAGS;
3049
        break;
3050
    case 0xf8: /* clc */
3051
        if (s->cc_op != CC_OP_DYNAMIC)
3052
            gen_op_set_cc_op(s->cc_op);
3053
        gen_op_clc();
3054
        s->cc_op = CC_OP_EFLAGS;
3055
        break;
3056
    case 0xf9: /* stc */
3057
        if (s->cc_op != CC_OP_DYNAMIC)
3058
            gen_op_set_cc_op(s->cc_op);
3059
        gen_op_stc();
3060
        s->cc_op = CC_OP_EFLAGS;
3061
        break;
3062
    case 0xfc: /* cld */
3063
        gen_op_cld();
3064
        break;
3065
    case 0xfd: /* std */
3066
        gen_op_std();
3067
        break;
3068

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

    
3273
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3274
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3275

    
3276
/* flags read by an operation */
3277
static uint16_t opc_read_flags[NB_OPS] = { 
3278
    [INDEX_op_aas] = CC_A,
3279
    [INDEX_op_aaa] = CC_A,
3280
    [INDEX_op_das] = CC_A | CC_C,
3281
    [INDEX_op_daa] = CC_A | CC_C,
3282

    
3283
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3284
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3285
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3286
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3287
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3288
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3289

    
3290
    [INDEX_op_into] = CC_O,
3291

    
3292
    [INDEX_op_jo_cc] = CC_O,
3293
    [INDEX_op_jb_cc] = CC_C,
3294
    [INDEX_op_jz_cc] = CC_Z,
3295
    [INDEX_op_jbe_cc] = CC_Z | CC_C,
3296
    [INDEX_op_js_cc] = CC_S,
3297
    [INDEX_op_jp_cc] = CC_P,
3298
    [INDEX_op_jl_cc] = CC_O | CC_S,
3299
    [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3300

    
3301
    [INDEX_op_jb_subb] = CC_C,
3302
    [INDEX_op_jb_subw] = CC_C,
3303
    [INDEX_op_jb_subl] = CC_C,
3304

    
3305
    [INDEX_op_jz_subb] = CC_Z,
3306
    [INDEX_op_jz_subw] = CC_Z,
3307
    [INDEX_op_jz_subl] = CC_Z,
3308

    
3309
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3310
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3311
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3312

    
3313
    [INDEX_op_js_subb] = CC_S,
3314
    [INDEX_op_js_subw] = CC_S,
3315
    [INDEX_op_js_subl] = CC_S,
3316

    
3317
    [INDEX_op_jl_subb] = CC_O | CC_S,
3318
    [INDEX_op_jl_subw] = CC_O | CC_S,
3319
    [INDEX_op_jl_subl] = CC_O | CC_S,
3320

    
3321
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3322
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3323
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3324

    
3325
    [INDEX_op_loopnzw] = CC_Z,
3326
    [INDEX_op_loopnzl] = CC_Z,
3327
    [INDEX_op_loopzw] = CC_Z,
3328
    [INDEX_op_loopzl] = CC_Z,
3329

    
3330
    [INDEX_op_seto_T0_cc] = CC_O,
3331
    [INDEX_op_setb_T0_cc] = CC_C,
3332
    [INDEX_op_setz_T0_cc] = CC_Z,
3333
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3334
    [INDEX_op_sets_T0_cc] = CC_S,
3335
    [INDEX_op_setp_T0_cc] = CC_P,
3336
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3337
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3338

    
3339
    [INDEX_op_setb_T0_subb] = CC_C,
3340
    [INDEX_op_setb_T0_subw] = CC_C,
3341
    [INDEX_op_setb_T0_subl] = CC_C,
3342

    
3343
    [INDEX_op_setz_T0_subb] = CC_Z,
3344
    [INDEX_op_setz_T0_subw] = CC_Z,
3345
    [INDEX_op_setz_T0_subl] = CC_Z,
3346

    
3347
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3348
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3349
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3350

    
3351
    [INDEX_op_sets_T0_subb] = CC_S,
3352
    [INDEX_op_sets_T0_subw] = CC_S,
3353
    [INDEX_op_sets_T0_subl] = CC_S,
3354

    
3355
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3356
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3357
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3358

    
3359
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3360
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3361
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3362

    
3363
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3364
    [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
3365
    [INDEX_op_cmc] = CC_C,
3366
    [INDEX_op_salc] = CC_C,
3367

    
3368
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3369
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3370
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3371
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3372
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3373
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3374
};
3375

    
3376
/* flags written by an operation */
3377
static uint16_t opc_write_flags[NB_OPS] = { 
3378
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3379
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3380
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3381
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3382
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3383
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3384
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3385
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3386
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3387
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3388
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3389
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3390
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3391
    [INDEX_op_incl_T0_cc] = CC_OSZAP,
3392
    [INDEX_op_decl_T0_cc] = CC_OSZAP,
3393
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3394

    
3395
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3396
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3397
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3398
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3399
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3400
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3401
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3402
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3403
    
3404
    /* bcd */
3405
    [INDEX_op_aam] = CC_OSZAPC,
3406
    [INDEX_op_aad] = CC_OSZAPC,
3407
    [INDEX_op_aas] = CC_OSZAPC,
3408
    [INDEX_op_aaa] = CC_OSZAPC,
3409
    [INDEX_op_das] = CC_OSZAPC,
3410
    [INDEX_op_daa] = CC_OSZAPC,
3411

    
3412
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3413
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3414
    [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC,
3415
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3416
    [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC,
3417
    [INDEX_op_clc] = CC_C,
3418
    [INDEX_op_stc] = CC_C,
3419
    [INDEX_op_cmc] = CC_C,
3420

    
3421
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3422
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3423
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3424
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3425
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3426
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3427

    
3428
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3429
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3430
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3431
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3432
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3433
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3434

    
3435
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3436
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3437
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3438

    
3439
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3440
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3441
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3442

    
3443
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3444
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3445
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3446

    
3447
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3448
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3449
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3450
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3451

    
3452
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3453
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3454
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3455
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3456

    
3457
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3458
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3459
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3460
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3461
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3462
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3463
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3464
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3465

    
3466
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3467
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3468
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3469
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3470

    
3471
#undef STRINGOP
3472
#define STRINGOP(x) \
3473
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3474
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3475
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3476
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3477
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3478
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3479
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3480
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3481
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3482

    
3483
    STRINGOP(scas)
3484
    STRINGOP(repz_scas)
3485
    STRINGOP(repnz_scas)
3486
    STRINGOP(cmps)
3487
    STRINGOP(repz_cmps)
3488
    STRINGOP(repnz_cmps)
3489

    
3490
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3491
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3492
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3493

    
3494
    [INDEX_op_cmpxchg8b] = CC_Z,
3495
};
3496

    
3497
/* simpler form of an operation if no flags need to be generated */
3498
static uint16_t opc_simpler[NB_OPS] = { 
3499
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3500
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3501
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3502
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3503
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3504
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3505
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3506
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3507

    
3508
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3509
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3510
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3511

    
3512
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3513
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3514
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3515

    
3516
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3517
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3518
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3519

    
3520
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3521
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3522
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3523

    
3524
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3525
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3526
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3527
};
3528

    
3529
static void optimize_flags_init(void)
3530
{
3531
    int i;
3532
    /* put default values in arrays */
3533
    for(i = 0; i < NB_OPS; i++) {
3534
        if (opc_simpler[i] == 0)
3535
            opc_simpler[i] = i;
3536
    }
3537
}
3538

    
3539
/* CPU flags computation optimization: we move backward thru the
3540
   generated code to see which flags are needed. The operation is
3541
   modified if suitable */
3542
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3543
{
3544
    uint16_t *opc_ptr;
3545
    int live_flags, write_flags, op;
3546

    
3547
    opc_ptr = opc_buf + opc_buf_len;
3548
    /* live_flags contains the flags needed by the next instructions
3549
       in the code. At the end of the bloc, we consider that all the
3550
       flags are live. */
3551
    live_flags = CC_OSZAPC;
3552
    while (opc_ptr > opc_buf) {
3553
        op = *--opc_ptr;
3554
        /* if none of the flags written by the instruction is used,
3555
           then we can try to find a simpler instruction */
3556
        write_flags = opc_write_flags[op];
3557
        if ((live_flags & write_flags) == 0) {
3558
            *opc_ptr = opc_simpler[op];
3559
        }
3560
        /* compute the live flags before the instruction */
3561
        live_flags &= ~write_flags;
3562
        live_flags |= opc_read_flags[op];
3563
    }
3564
}
3565

    
3566

    
3567
#ifdef DEBUG_DISAS
3568
static const char *op_str[] = {
3569
#define DEF(s, n) #s,
3570
#include "opc-i386.h"
3571
#undef DEF
3572
};
3573

    
3574
static uint8_t op_nb_args[] = {
3575
#define DEF(s, n) n,
3576
#include "opc-i386.h"
3577
#undef DEF
3578
};
3579

    
3580
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3581
{
3582
    const uint16_t *opc_ptr;
3583
    const uint32_t *opparam_ptr;
3584
    int c, n, i;
3585

    
3586
    opc_ptr = opc_buf;
3587
    opparam_ptr = opparam_buf;
3588
    for(;;) {
3589
        c = *opc_ptr++;
3590
        n = op_nb_args[c];
3591
        fprintf(logfile, "0x%04x: %s", opc_ptr - opc_buf - 1, op_str[c]);
3592
        for(i = 0; i < n; i++) {
3593
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
3594
        }
3595
        fprintf(logfile, "\n");
3596
        if (c == INDEX_op_end)
3597
            break;
3598
        opparam_ptr += n;
3599
    }
3600
}
3601

    
3602
#endif
3603

    
3604
/* XXX: make this buffer thread safe */
3605
/* XXX: make safe guess about sizes */
3606
#define MAX_OP_PER_INSTR 32
3607
#define OPC_BUF_SIZE 512
3608
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3609

    
3610
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3611

    
3612
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3613
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3614

    
3615
/* return non zero if the very first instruction is invalid so that
3616
   the virtual CPU can trigger an exception. */
3617
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3618
                     int *gen_code_size_ptr,
3619
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3620
{
3621
    DisasContext dc1, *dc = &dc1;
3622
    uint8_t *pc_ptr;
3623
    uint16_t *gen_opc_end;
3624
    int gen_code_size;
3625
    long ret;
3626
    
3627
    /* generate intermediate code */
3628

    
3629
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3630
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3631
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3632
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3633
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3634
    dc->cc_op = CC_OP_DYNAMIC;
3635
    dc->cs_base = cs_base;
3636

    
3637
    gen_opc_ptr = gen_opc_buf;
3638
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3639
    gen_opparam_ptr = gen_opparam_buf;
3640

    
3641
    dc->is_jmp = 0;
3642
    pc_ptr = pc_start;
3643
    do {
3644
        ret = disas_insn(dc, pc_ptr);
3645
        if (ret == -1) {
3646
            /* we trigger an illegal instruction operation only if it
3647
               is the first instruction. Otherwise, we simply stop
3648
               generating the code just before it */
3649
            if (pc_ptr == pc_start)
3650
                return -1;
3651
            else
3652
                break;
3653
        }
3654
        pc_ptr = (void *)ret;
3655
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3656
    /* we must store the eflags state if it is not already done */
3657
    if (dc->cc_op != CC_OP_DYNAMIC)
3658
        gen_op_set_cc_op(dc->cc_op);
3659
    if (dc->is_jmp != 1) {
3660
        /* we add an additionnal jmp to update the simulated PC */
3661
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3662
    }
3663
    *gen_opc_ptr = INDEX_op_end;
3664

    
3665
#ifdef DEBUG_DISAS
3666
    if (loglevel) {
3667
        fprintf(logfile, "----------------\n");
3668
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3669
        disas(logfile, pc_start, pc_ptr - pc_start,
3670
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3671
        fprintf(logfile, "\n");
3672
        
3673
        fprintf(logfile, "OP:\n");
3674
        dump_ops(gen_opc_buf, gen_opparam_buf);
3675
        fprintf(logfile, "\n");
3676
    }
3677
#endif
3678

    
3679
    /* optimize flag computations */
3680
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3681

    
3682
#ifdef DEBUG_DISAS
3683
    if (loglevel) {
3684
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3685
        dump_ops(gen_opc_buf, gen_opparam_buf);
3686
        fprintf(logfile, "\n");
3687
    }
3688
#endif
3689

    
3690
    /* generate machine code */
3691
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3692
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3693
    *gen_code_size_ptr = gen_code_size;
3694

    
3695
#ifdef DEBUG_DISAS
3696
    if (loglevel) {
3697
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3698
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3699
        fprintf(logfile, "\n");
3700
        fflush(logfile);
3701
    }
3702
#endif
3703
    return 0;
3704
}
3705

    
3706
CPUX86State *cpu_x86_init(void)
3707
{
3708
    CPUX86State *env;
3709
    int i;
3710
    static int inited;
3711

    
3712
    cpu_x86_tblocks_init();
3713

    
3714
    env = malloc(sizeof(CPUX86State));
3715
    if (!env)
3716
        return NULL;
3717
    memset(env, 0, sizeof(CPUX86State));
3718
    /* basic FPU init */
3719
    for(i = 0;i < 8; i++)
3720
        env->fptags[i] = 1;
3721
    env->fpuc = 0x37f;
3722
    /* flags setup : we activate the IRQs by default as in user mode */
3723
    env->eflags = 0x2 | IF_MASK;
3724

    
3725
    /* init various static tables */
3726
    if (!inited) {
3727
        inited = 1;
3728
        optimize_flags_init();
3729
    }
3730
    return env;
3731
}
3732

    
3733
void cpu_x86_close(CPUX86State *env)
3734
{
3735
    free(env);
3736
}