Statistics
| Branch: | Revision:

root / translate-i386.c @ 5132455e

History | View | Annotate | Download (106.3 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
/* XXX: move that elsewhere */
36
static uint16_t *gen_opc_ptr;
37
static uint32_t *gen_opparam_ptr;
38
int __op_param1, __op_param2, __op_param3;
39

    
40
#ifdef __i386__
41
static inline void flush_icache_range(unsigned long start, unsigned long stop)
42
{
43
}
44
#endif
45

    
46
#ifdef __s390__
47
static inline void flush_icache_range(unsigned long start, unsigned long stop)
48
{
49
}
50
#endif
51

    
52
#ifdef __ia64__
53
static inline void flush_icache_range(unsigned long start, unsigned long stop)
54
{
55
}
56
#endif
57

    
58
#ifdef __powerpc__
59

    
60
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
61

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

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

    
81
#ifdef __alpha__
82
static inline void flush_icache_range(unsigned long start, unsigned long stop)
83
{
84
    asm ("imb");
85
}
86
#endif
87

    
88
#ifdef __sparc__
89

    
90
static void inline flush_icache_range(unsigned long start, unsigned long stop)
91
{
92
        unsigned long p;
93

    
94
        p = start & ~(8UL - 1UL);
95
        stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
96

    
97
        for (; p < stop; p += 8)
98
                __asm__ __volatile__("flush\t%0" : : "r" (p));
99
}
100

    
101
#endif
102

    
103
extern FILE *logfile;
104
extern int loglevel;
105

    
106
#define PREFIX_REPZ   0x01
107
#define PREFIX_REPNZ  0x02
108
#define PREFIX_LOCK   0x04
109
#define PREFIX_DATA   0x08
110
#define PREFIX_ADR    0x10
111
#define PREFIX_FWAIT  0x20
112

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

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

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

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

    
165
#include "op-i386.h"
166

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
630

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

    
636

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

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

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

    
678

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
909
    if (s->aflag) {
910

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1366
static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1367
{
1368
    if (s->cc_op != CC_OP_DYNAMIC)
1369
        gen_op_set_cc_op(s->cc_op);
1370
    gen_op_jmp_im(cur_eip);
1371
    gen_op_raise_exception(trapno);
1372
    s->is_jmp = 1;
1373
}
1374

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

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

    
1433
    if (prefixes & PREFIX_DATA)
1434
        dflag ^= 1;
1435
    if (prefixes & PREFIX_ADR)
1436
        aflag ^= 1;
1437

    
1438
    s->prefix = prefixes;
1439
    s->aflag = aflag;
1440
    s->dflag = dflag;
1441

    
1442
    /* lock generation */
1443
    if (prefixes & PREFIX_LOCK)
1444
        gen_op_lock();
1445

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

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

    
1515
    case 0x80: /* GRP1 */
1516
    case 0x81:
1517
    case 0x83:
1518
        {
1519
            int val;
1520

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

    
1539
            switch(b) {
1540
            default:
1541
            case 0x80:
1542
            case 0x81:
1543
                val = insn_get(s, ot);
1544
                break;
1545
            case 0x83:
1546
                val = (int8_t)insn_get(s, OT_BYTE);
1547
                break;
1548
            }
1549

    
1550
            gen_opi(s, op, ot, opreg, val);
1551
            if (op != 7 && mod != 3) {
1552
                gen_op_st_T0_A0[ot]();
1553
            }
1554
        }
1555
        break;
1556

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

    
1574
        modrm = ldub(s->pc++);
1575
        mod = (modrm >> 6) & 3;
1576
        rm = modrm & 7;
1577
        op = (modrm >> 3) & 7;
1578
        if (mod != 3) {
1579
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1580
            gen_op_ld_T0_A0[ot]();
1581
        } else {
1582
            gen_op_mov_TN_reg[ot][0][rm]();
1583
        }
1584

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

    
1672
    case 0xfe: /* GRP4 */
1673
    case 0xff: /* GRP5 */
1674
        if ((b & 1) == 0)
1675
            ot = OT_BYTE;
1676
        else
1677
            ot = dflag ? OT_LONG : OT_WORD;
1678

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

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

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

    
1758
    case 0x84: /* test Ev, Gv */
1759
    case 0x85: 
1760
        if ((b & 1) == 0)
1761
            ot = OT_BYTE;
1762
        else
1763
            ot = dflag ? OT_LONG : OT_WORD;
1764

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

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

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

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

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

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

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

    
2254
            /* simpler op */
2255
            if (shift == 0) {
2256
                gen_shift(s, op, ot, opreg, OR_ECX);
2257
            } else {
2258
                if (shift == 2) {
2259
                    shift = ldub(s->pc++);
2260
                }
2261
                gen_shifti(s, op, ot, opreg, shift);
2262
            }
2263

    
2264
            if (mod != 3) {
2265
                gen_op_st_T0_A0[ot]();
2266
            }
2267
        }
2268
        break;
2269
    case 0xd0:
2270
    case 0xd1:
2271
        /* shift Ev,1 */
2272
        shift = 1;
2273
        goto grp2;
2274
    case 0xd2:
2275
    case 0xd3:
2276
        /* shift Ev,cl */
2277
        shift = 0;
2278
        goto grp2;
2279

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

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

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

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

    
2693
    case 0xa4: /* movsS */
2694
    case 0xa5:
2695
        if ((b & 1) == 0)
2696
            ot = OT_BYTE;
2697
        else
2698
            ot = dflag ? OT_LONG : OT_WORD;
2699

    
2700
        if (prefixes & PREFIX_REPZ) {
2701
            gen_string_ds(s, ot, gen_op_movs + 9);
2702
        } else {
2703
            gen_string_ds(s, ot, gen_op_movs);
2704
        }
2705
        break;
2706
        
2707
    case 0xaa: /* stosS */
2708
    case 0xab:
2709
        if ((b & 1) == 0)
2710
            ot = OT_BYTE;
2711
        else
2712
            ot = dflag ? OT_LONG : OT_WORD;
2713

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

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

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

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

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

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

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

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

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

    
3373
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3374
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3375

    
3376
/* flags read by an operation */
3377
static uint16_t opc_read_flags[NB_OPS] = { 
3378
    [INDEX_op_aas] = CC_A,
3379
    [INDEX_op_aaa] = CC_A,
3380
    [INDEX_op_das] = CC_A | CC_C,
3381
    [INDEX_op_daa] = CC_A | CC_C,
3382

    
3383
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3384
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3385
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3386
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3387
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3388
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3389

    
3390
    /* subtle: due to the incl/decl implementation, C is used */
3391
    [INDEX_op_incl_T0_cc] = CC_C, 
3392
    [INDEX_op_decl_T0_cc] = CC_C,
3393

    
3394
    [INDEX_op_into] = CC_O,
3395

    
3396
    [INDEX_op_jo_cc] = CC_O,
3397
    [INDEX_op_jb_cc] = CC_C,
3398
    [INDEX_op_jz_cc] = CC_Z,
3399
    [INDEX_op_jbe_cc] = CC_Z | CC_C,
3400
    [INDEX_op_js_cc] = CC_S,
3401
    [INDEX_op_jp_cc] = CC_P,
3402
    [INDEX_op_jl_cc] = CC_O | CC_S,
3403
    [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3404

    
3405
    [INDEX_op_jb_subb] = CC_C,
3406
    [INDEX_op_jb_subw] = CC_C,
3407
    [INDEX_op_jb_subl] = CC_C,
3408

    
3409
    [INDEX_op_jz_subb] = CC_Z,
3410
    [INDEX_op_jz_subw] = CC_Z,
3411
    [INDEX_op_jz_subl] = CC_Z,
3412

    
3413
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3414
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3415
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3416

    
3417
    [INDEX_op_js_subb] = CC_S,
3418
    [INDEX_op_js_subw] = CC_S,
3419
    [INDEX_op_js_subl] = CC_S,
3420

    
3421
    [INDEX_op_jl_subb] = CC_O | CC_S,
3422
    [INDEX_op_jl_subw] = CC_O | CC_S,
3423
    [INDEX_op_jl_subl] = CC_O | CC_S,
3424

    
3425
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3426
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3427
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3428

    
3429
    [INDEX_op_loopnzw] = CC_Z,
3430
    [INDEX_op_loopnzl] = CC_Z,
3431
    [INDEX_op_loopzw] = CC_Z,
3432
    [INDEX_op_loopzl] = CC_Z,
3433

    
3434
    [INDEX_op_seto_T0_cc] = CC_O,
3435
    [INDEX_op_setb_T0_cc] = CC_C,
3436
    [INDEX_op_setz_T0_cc] = CC_Z,
3437
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3438
    [INDEX_op_sets_T0_cc] = CC_S,
3439
    [INDEX_op_setp_T0_cc] = CC_P,
3440
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3441
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3442

    
3443
    [INDEX_op_setb_T0_subb] = CC_C,
3444
    [INDEX_op_setb_T0_subw] = CC_C,
3445
    [INDEX_op_setb_T0_subl] = CC_C,
3446

    
3447
    [INDEX_op_setz_T0_subb] = CC_Z,
3448
    [INDEX_op_setz_T0_subw] = CC_Z,
3449
    [INDEX_op_setz_T0_subl] = CC_Z,
3450

    
3451
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3452
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3453
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3454

    
3455
    [INDEX_op_sets_T0_subb] = CC_S,
3456
    [INDEX_op_sets_T0_subw] = CC_S,
3457
    [INDEX_op_sets_T0_subl] = CC_S,
3458

    
3459
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3460
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3461
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3462

    
3463
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3464
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3465
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3466

    
3467
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3468
    [INDEX_op_cmc] = CC_C,
3469
    [INDEX_op_salc] = CC_C,
3470

    
3471
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3472
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3473
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3474
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3475
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3476
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3477
};
3478

    
3479
/* flags written by an operation */
3480
static uint16_t opc_write_flags[NB_OPS] = { 
3481
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3482
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3483
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3484
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3485
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3486
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3487
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3488
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3489
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3490
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3491
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3492
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3493
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3494
    /* subtle: due to the incl/decl implementation, C is used */
3495
    [INDEX_op_incl_T0_cc] = CC_OSZAPC, 
3496
    [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3497
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3498

    
3499
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3500
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3501
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3502
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3503
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3504
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3505
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3506
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3507
    
3508
    /* bcd */
3509
    [INDEX_op_aam] = CC_OSZAPC,
3510
    [INDEX_op_aad] = CC_OSZAPC,
3511
    [INDEX_op_aas] = CC_OSZAPC,
3512
    [INDEX_op_aaa] = CC_OSZAPC,
3513
    [INDEX_op_das] = CC_OSZAPC,
3514
    [INDEX_op_daa] = CC_OSZAPC,
3515

    
3516
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3517
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3518
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3519
    [INDEX_op_clc] = CC_C,
3520
    [INDEX_op_stc] = CC_C,
3521
    [INDEX_op_cmc] = CC_C,
3522

    
3523
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3524
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3525
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3526
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3527
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3528
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3529

    
3530
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3531
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3532
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3533
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3534
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3535
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3536

    
3537
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3538
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3539
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3540

    
3541
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3542
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3543
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3544

    
3545
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3546
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3547
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3548

    
3549
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3550
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3551
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3552
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3553

    
3554
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3555
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3556
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3557
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3558

    
3559
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3560
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3561
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3562
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3563
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3564
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3565
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3566
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3567

    
3568
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3569
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3570
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3571
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3572

    
3573
#undef STRINGOP
3574
#define STRINGOP(x) \
3575
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3576
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3577
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3578
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3579
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3580
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3581
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3582
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3583
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3584

    
3585
    STRINGOP(scas)
3586
    STRINGOP(repz_scas)
3587
    STRINGOP(repnz_scas)
3588
    STRINGOP(cmps)
3589
    STRINGOP(repz_cmps)
3590
    STRINGOP(repnz_cmps)
3591

    
3592
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3593
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3594
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3595

    
3596
    [INDEX_op_cmpxchg8b] = CC_Z,
3597
    [INDEX_op_lar] = CC_Z,
3598
    [INDEX_op_lsl] = CC_Z,
3599
};
3600

    
3601
/* simpler form of an operation if no flags need to be generated */
3602
static uint16_t opc_simpler[NB_OPS] = { 
3603
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3604
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3605
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3606
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3607
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3608
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3609
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3610
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3611

    
3612
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3613
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3614
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3615

    
3616
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3617
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3618
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3619

    
3620
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3621
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3622
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3623

    
3624
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3625
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3626
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3627

    
3628
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3629
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3630
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3631
};
3632

    
3633
static void optimize_flags_init(void)
3634
{
3635
    int i;
3636
    /* put default values in arrays */
3637
    for(i = 0; i < NB_OPS; i++) {
3638
        if (opc_simpler[i] == 0)
3639
            opc_simpler[i] = i;
3640
    }
3641
}
3642

    
3643
/* CPU flags computation optimization: we move backward thru the
3644
   generated code to see which flags are needed. The operation is
3645
   modified if suitable */
3646
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3647
{
3648
    uint16_t *opc_ptr;
3649
    int live_flags, write_flags, op;
3650

    
3651
    opc_ptr = opc_buf + opc_buf_len;
3652
    /* live_flags contains the flags needed by the next instructions
3653
       in the code. At the end of the bloc, we consider that all the
3654
       flags are live. */
3655
    live_flags = CC_OSZAPC;
3656
    while (opc_ptr > opc_buf) {
3657
        op = *--opc_ptr;
3658
        /* if none of the flags written by the instruction is used,
3659
           then we can try to find a simpler instruction */
3660
        write_flags = opc_write_flags[op];
3661
        if ((live_flags & write_flags) == 0) {
3662
            *opc_ptr = opc_simpler[op];
3663
        }
3664
        /* compute the live flags before the instruction */
3665
        live_flags &= ~write_flags;
3666
        live_flags |= opc_read_flags[op];
3667
    }
3668
}
3669

    
3670

    
3671
#ifdef DEBUG_DISAS
3672
static const char *op_str[] = {
3673
#define DEF(s, n) #s,
3674
#include "opc-i386.h"
3675
#undef DEF
3676
};
3677

    
3678
static uint8_t op_nb_args[] = {
3679
#define DEF(s, n) n,
3680
#include "opc-i386.h"
3681
#undef DEF
3682
};
3683

    
3684
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3685
{
3686
    const uint16_t *opc_ptr;
3687
    const uint32_t *opparam_ptr;
3688
    int c, n, i;
3689

    
3690
    opc_ptr = opc_buf;
3691
    opparam_ptr = opparam_buf;
3692
    for(;;) {
3693
        c = *opc_ptr++;
3694
        n = op_nb_args[c];
3695
        fprintf(logfile, "0x%04x: %s", 
3696
                (int)(opc_ptr - opc_buf - 1), op_str[c]);
3697
        for(i = 0; i < n; i++) {
3698
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
3699
        }
3700
        fprintf(logfile, "\n");
3701
        if (c == INDEX_op_end)
3702
            break;
3703
        opparam_ptr += n;
3704
    }
3705
}
3706

    
3707
#endif
3708

    
3709
/* XXX: make this buffer thread safe */
3710
/* XXX: make safe guess about sizes */
3711
#define MAX_OP_PER_INSTR 32
3712
#define OPC_BUF_SIZE 512
3713
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3714

    
3715
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3716

    
3717
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3718
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3719

    
3720
/* return non zero if the very first instruction is invalid so that
3721
   the virtual CPU can trigger an exception. 
3722

3723
   '*code_size_ptr' contains the target code size including the
3724
   instruction which triggered an exception, except in case of invalid
3725
   illegal opcode. It must never exceed one target page. 
3726
   
3727
   '*gen_code_size_ptr' contains the size of the generated code (host
3728
   code).
3729
*/
3730
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3731
                     int *gen_code_size_ptr,
3732
                     uint8_t *pc_start,  uint8_t *cs_base, int flags,
3733
                     int *code_size_ptr)
3734
{
3735
    DisasContext dc1, *dc = &dc1;
3736
    uint8_t *pc_ptr;
3737
    uint16_t *gen_opc_end;
3738
    int gen_code_size;
3739
    long ret;
3740
    
3741
    /* generate intermediate code */
3742

    
3743
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3744
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3745
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3746
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3747
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3748
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3749
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3750
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3751
    dc->cc_op = CC_OP_DYNAMIC;
3752
    dc->cs_base = cs_base;
3753

    
3754
    gen_opc_ptr = gen_opc_buf;
3755
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3756
    gen_opparam_ptr = gen_opparam_buf;
3757

    
3758
    dc->is_jmp = 0;
3759
    pc_ptr = pc_start;
3760
    do {
3761
        ret = disas_insn(dc, pc_ptr);
3762
        if (ret == -1) {
3763
            /* we trigger an illegal instruction operation only if it
3764
               is the first instruction. Otherwise, we simply stop
3765
               generating the code just before it */
3766
            if (pc_ptr == pc_start)
3767
                return -1;
3768
            else
3769
                break;
3770
        }
3771
        pc_ptr = (void *)ret;
3772
        /* if single step mode, we generate only one instruction and
3773
           generate an exception */
3774
        if (dc->tf)
3775
            break;
3776
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
3777
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3778
    /* we must store the eflags state if it is not already done */
3779
    if (dc->cc_op != CC_OP_DYNAMIC)
3780
        gen_op_set_cc_op(dc->cc_op);
3781
    if (dc->is_jmp != 1) {
3782
        /* we add an additionnal jmp to update the simulated PC */
3783
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3784
    }
3785
    if (dc->tf) {
3786
        gen_op_raise_exception(EXCP01_SSTP);
3787
    }
3788

    
3789
    *gen_opc_ptr = INDEX_op_end;
3790

    
3791
#ifdef DEBUG_DISAS
3792
    if (loglevel) {
3793
        fprintf(logfile, "----------------\n");
3794
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3795
        disas(logfile, pc_start, pc_ptr - pc_start,
3796
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3797
        fprintf(logfile, "\n");
3798

    
3799
        fprintf(logfile, "OP:\n");
3800
        dump_ops(gen_opc_buf, gen_opparam_buf);
3801
        fprintf(logfile, "\n");
3802
    }
3803
#endif
3804

    
3805
    /* optimize flag computations */
3806
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3807

    
3808
#ifdef DEBUG_DISAS
3809
    if (loglevel) {
3810
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3811
        dump_ops(gen_opc_buf, gen_opparam_buf);
3812
        fprintf(logfile, "\n");
3813
    }
3814
#endif
3815

    
3816
    /* generate machine code */
3817
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3818
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3819
    *gen_code_size_ptr = gen_code_size;
3820
    *code_size_ptr = pc_ptr - pc_start;
3821
#ifdef DEBUG_DISAS
3822
    if (loglevel) {
3823
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3824
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3825
        fprintf(logfile, "\n");
3826
        fflush(logfile);
3827
    }
3828
#endif
3829
    return 0;
3830
}
3831

    
3832
CPUX86State *cpu_x86_init(void)
3833
{
3834
    CPUX86State *env;
3835
    int i;
3836
    static int inited;
3837

    
3838
    cpu_x86_tblocks_init();
3839

    
3840
    env = malloc(sizeof(CPUX86State));
3841
    if (!env)
3842
        return NULL;
3843
    memset(env, 0, sizeof(CPUX86State));
3844
    /* basic FPU init */
3845
    for(i = 0;i < 8; i++)
3846
        env->fptags[i] = 1;
3847
    env->fpuc = 0x37f;
3848
    /* flags setup : we activate the IRQs by default as in user mode */
3849
    env->eflags = 0x2 | IF_MASK;
3850

    
3851
    /* init various static tables */
3852
    if (!inited) {
3853
        inited = 1;
3854
        optimize_flags_init();
3855
        page_init();
3856
    }
3857
    return env;
3858
}
3859

    
3860
void cpu_x86_close(CPUX86State *env)
3861
{
3862
    free(env);
3863
}
3864

    
3865
static const char *cc_op_str[] = {
3866
    "DYNAMIC",
3867
    "EFLAGS",
3868
    "MUL",
3869
    "ADDB",
3870
    "ADDW",
3871
    "ADDL",
3872
    "ADCB",
3873
    "ADCW",
3874
    "ADCL",
3875
    "SUBB",
3876
    "SUBW",
3877
    "SUBL",
3878
    "SBBB",
3879
    "SBBW",
3880
    "SBBL",
3881
    "LOGICB",
3882
    "LOGICW",
3883
    "LOGICL",
3884
    "INCB",
3885
    "INCW",
3886
    "INCL",
3887
    "DECB",
3888
    "DECW",
3889
    "DECL",
3890
    "SHLB",
3891
    "SHLW",
3892
    "SHLL",
3893
    "SARB",
3894
    "SARW",
3895
    "SARL",
3896
};
3897

    
3898
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3899
{
3900
    int eflags;
3901
    char cc_op_name[32];
3902

    
3903
    eflags = env->eflags;
3904
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3905
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3906
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3907
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
3908
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
3909
            env->eip, eflags,
3910
            eflags & DF_MASK ? 'D' : '-',
3911
            eflags & CC_O ? 'O' : '-',
3912
            eflags & CC_S ? 'S' : '-',
3913
            eflags & CC_Z ? 'Z' : '-',
3914
            eflags & CC_A ? 'A' : '-',
3915
            eflags & CC_P ? 'P' : '-',
3916
            eflags & CC_C ? 'C' : '-');
3917
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3918
            env->segs[R_CS],
3919
            env->segs[R_SS],
3920
            env->segs[R_DS],
3921
            env->segs[R_ES],
3922
            env->segs[R_FS],
3923
            env->segs[R_GS]);
3924
    if (flags & X86_DUMP_CCOP) {
3925
        if ((unsigned)env->cc_op < CC_OP_NB)
3926
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
3927
        else
3928
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
3929
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
3930
                env->cc_src, env->cc_dst, cc_op_name);
3931
    }
3932
    if (flags & X86_DUMP_FPU) {
3933
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
3934
                (double)env->fpregs[0], 
3935
                (double)env->fpregs[1], 
3936
                (double)env->fpregs[2], 
3937
                (double)env->fpregs[3]);
3938
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
3939
                (double)env->fpregs[4], 
3940
                (double)env->fpregs[5], 
3941
                (double)env->fpregs[7], 
3942
                (double)env->fpregs[8]);
3943
    }
3944
}