Statistics
| Branch: | Revision:

root / translate-i386.c @ 366c1b8b

History | View | Annotate | Download (105.9 kB)

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

    
28
#include "disas.h"
29

    
30
#define DEBUG_DISAS
31

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

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

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

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

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

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

    
62
#ifdef __powerpc__
63

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

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

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

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

    
92
#ifdef __sparc__
93

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

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

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

    
105
#endif
106

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

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

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

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

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

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

    
169
#include "op-i386.h"
170

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
634

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

    
640

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

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

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

    
682

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
913
    if (s->aflag) {
914

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1437
    if (prefixes & PREFIX_DATA)
1438
        dflag ^= 1;
1439
    if (prefixes & PREFIX_ADR)
1440
        aflag ^= 1;
1441

    
1442
    s->prefix = prefixes;
1443
    s->aflag = aflag;
1444
    s->dflag = dflag;
1445

    
1446
    /* lock generation */
1447
    if (prefixes & PREFIX_LOCK)
1448
        gen_op_lock();
1449

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

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

    
1519
    case 0x80: /* GRP1 */
1520
    case 0x81:
1521
    case 0x83:
1522
        {
1523
            int val;
1524

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

    
1543
            switch(b) {
1544
            default:
1545
            case 0x80:
1546
            case 0x81:
1547
                val = insn_get(s, ot);
1548
                break;
1549
            case 0x83:
1550
                val = (int8_t)insn_get(s, OT_BYTE);
1551
                break;
1552
            }
1553

    
1554
            gen_opi(s, op, ot, opreg, val);
1555
            if (op != 7 && mod != 3) {
1556
                gen_op_st_T0_A0[ot]();
1557
            }
1558
        }
1559
        break;
1560

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

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

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

    
1676
    case 0xfe: /* GRP4 */
1677
    case 0xff: /* GRP5 */
1678
        if ((b & 1) == 0)
1679
            ot = OT_BYTE;
1680
        else
1681
            ot = dflag ? OT_LONG : OT_WORD;
1682

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

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

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

    
1762
    case 0x84: /* test Ev, Gv */
1763
    case 0x85: 
1764
        if ((b & 1) == 0)
1765
            ot = OT_BYTE;
1766
        else
1767
            ot = dflag ? OT_LONG : OT_WORD;
1768

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2697
    case 0xa4: /* movsS */
2698
    case 0xa5:
2699
        if ((b & 1) == 0)
2700
            ot = OT_BYTE;
2701
        else
2702
            ot = dflag ? OT_LONG : OT_WORD;
2703

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

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

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

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

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

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

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

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

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

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

    
3376
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3377
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3378

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

    
3386
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3387
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3388
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3389
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3390
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3391
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3392

    
3393
    /* subtle: due to the incl/decl implementation, C is used */
3394
    [INDEX_op_incl_T0_cc] = CC_C, 
3395
    [INDEX_op_decl_T0_cc] = CC_C,
3396

    
3397
    [INDEX_op_into] = CC_O,
3398

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

    
3408
    [INDEX_op_jb_subb] = CC_C,
3409
    [INDEX_op_jb_subw] = CC_C,
3410
    [INDEX_op_jb_subl] = CC_C,
3411

    
3412
    [INDEX_op_jz_subb] = CC_Z,
3413
    [INDEX_op_jz_subw] = CC_Z,
3414
    [INDEX_op_jz_subl] = CC_Z,
3415

    
3416
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3417
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3418
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3419

    
3420
    [INDEX_op_js_subb] = CC_S,
3421
    [INDEX_op_js_subw] = CC_S,
3422
    [INDEX_op_js_subl] = CC_S,
3423

    
3424
    [INDEX_op_jl_subb] = CC_O | CC_S,
3425
    [INDEX_op_jl_subw] = CC_O | CC_S,
3426
    [INDEX_op_jl_subl] = CC_O | CC_S,
3427

    
3428
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3429
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3430
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3431

    
3432
    [INDEX_op_loopnzw] = CC_Z,
3433
    [INDEX_op_loopnzl] = CC_Z,
3434
    [INDEX_op_loopzw] = CC_Z,
3435
    [INDEX_op_loopzl] = CC_Z,
3436

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

    
3446
    [INDEX_op_setb_T0_subb] = CC_C,
3447
    [INDEX_op_setb_T0_subw] = CC_C,
3448
    [INDEX_op_setb_T0_subl] = CC_C,
3449

    
3450
    [INDEX_op_setz_T0_subb] = CC_Z,
3451
    [INDEX_op_setz_T0_subw] = CC_Z,
3452
    [INDEX_op_setz_T0_subl] = CC_Z,
3453

    
3454
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3455
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3456
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3457

    
3458
    [INDEX_op_sets_T0_subb] = CC_S,
3459
    [INDEX_op_sets_T0_subw] = CC_S,
3460
    [INDEX_op_sets_T0_subl] = CC_S,
3461

    
3462
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3463
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3464
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3465

    
3466
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3467
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3468
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3469

    
3470
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3471
    [INDEX_op_cmc] = CC_C,
3472
    [INDEX_op_salc] = CC_C,
3473

    
3474
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3475
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3476
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3477
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3478
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3479
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3480
};
3481

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

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

    
3519
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3520
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3521
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3522
    [INDEX_op_clc] = CC_C,
3523
    [INDEX_op_stc] = CC_C,
3524
    [INDEX_op_cmc] = CC_C,
3525

    
3526
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3527
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3528
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3529
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3530
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3531
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3532

    
3533
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3534
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3535
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3536
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3537
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3538
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3539

    
3540
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3541
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3542
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3543

    
3544
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3545
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3546
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3547

    
3548
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3549
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3550
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3551

    
3552
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3553
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3554
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3555
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3556

    
3557
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3558
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3559
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3560
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3561

    
3562
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3563
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3564
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3565
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3566
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3567
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3568
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3569
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3570

    
3571
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3572
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3573
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3574
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3575

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

    
3588
    STRINGOP(scas)
3589
    STRINGOP(repz_scas)
3590
    STRINGOP(repnz_scas)
3591
    STRINGOP(cmps)
3592
    STRINGOP(repz_cmps)
3593
    STRINGOP(repnz_cmps)
3594

    
3595
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3596
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3597
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3598

    
3599
    [INDEX_op_cmpxchg8b] = CC_Z,
3600
    [INDEX_op_lar] = CC_Z,
3601
    [INDEX_op_lsl] = CC_Z,
3602
};
3603

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

    
3615
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3616
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3617
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3618

    
3619
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3620
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3621
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3622

    
3623
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3624
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3625
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3626

    
3627
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3628
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3629
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3630

    
3631
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3632
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3633
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3634
};
3635

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

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

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

    
3673

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

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

    
3687
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3688
{
3689
    const uint16_t *opc_ptr;
3690
    const uint32_t *opparam_ptr;
3691
    int c, n, i;
3692

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

    
3710
#endif
3711

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

    
3718
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3719

    
3720
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3721
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3722

    
3723
/* return non zero if the very first instruction is invalid so that
3724
   the virtual CPU can trigger an exception. */
3725
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3726
                     int *gen_code_size_ptr,
3727
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3728
{
3729
    DisasContext dc1, *dc = &dc1;
3730
    uint8_t *pc_ptr;
3731
    uint16_t *gen_opc_end;
3732
    int gen_code_size;
3733
    long ret;
3734
    
3735
    /* generate intermediate code */
3736

    
3737
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3738
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3739
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3740
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3741
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3742
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3743
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3744
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3745
    dc->cc_op = CC_OP_DYNAMIC;
3746
    dc->cs_base = cs_base;
3747

    
3748
    gen_opc_ptr = gen_opc_buf;
3749
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3750
    gen_opparam_ptr = gen_opparam_buf;
3751

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

    
3782
    *gen_opc_ptr = INDEX_op_end;
3783

    
3784
#ifdef DEBUG_DISAS
3785
    if (loglevel) {
3786
        fprintf(logfile, "----------------\n");
3787
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3788
        disas(logfile, pc_start, pc_ptr - pc_start,
3789
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3790
        fprintf(logfile, "\n");
3791

    
3792
        fprintf(logfile, "OP:\n");
3793
        dump_ops(gen_opc_buf, gen_opparam_buf);
3794
        fprintf(logfile, "\n");
3795
    }
3796
#endif
3797

    
3798
    /* optimize flag computations */
3799
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3800

    
3801
#ifdef DEBUG_DISAS
3802
    if (loglevel) {
3803
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3804
        dump_ops(gen_opc_buf, gen_opparam_buf);
3805
        fprintf(logfile, "\n");
3806
    }
3807
#endif
3808

    
3809
    /* generate machine code */
3810
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3811
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3812
    *gen_code_size_ptr = gen_code_size;
3813

    
3814
#ifdef DEBUG_DISAS
3815
    if (loglevel) {
3816
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3817
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3818
        fprintf(logfile, "\n");
3819
        fflush(logfile);
3820
    }
3821
#endif
3822
    return 0;
3823
}
3824

    
3825
CPUX86State *cpu_x86_init(void)
3826
{
3827
    CPUX86State *env;
3828
    int i;
3829
    static int inited;
3830

    
3831
    cpu_x86_tblocks_init();
3832

    
3833
    env = malloc(sizeof(CPUX86State));
3834
    if (!env)
3835
        return NULL;
3836
    memset(env, 0, sizeof(CPUX86State));
3837
    /* basic FPU init */
3838
    for(i = 0;i < 8; i++)
3839
        env->fptags[i] = 1;
3840
    env->fpuc = 0x37f;
3841
    /* flags setup : we activate the IRQs by default as in user mode */
3842
    env->eflags = 0x2 | IF_MASK;
3843

    
3844
    /* init various static tables */
3845
    if (!inited) {
3846
        inited = 1;
3847
        optimize_flags_init();
3848
    }
3849
    return env;
3850
}
3851

    
3852
void cpu_x86_close(CPUX86State *env)
3853
{
3854
    free(env);
3855
}
3856

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

    
3890
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3891
{
3892
    int eflags;
3893
    char cc_op_name[32];
3894

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