Statistics
| Branch: | Revision:

root / translate-i386.c @ a37904dd

History | View | Annotate | Download (106.8 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
#include "exec.h"
35

    
36
/* XXX: move that elsewhere */
37
static uint16_t *gen_opc_ptr;
38
static uint32_t *gen_opparam_ptr;
39
int __op_param1, __op_param2, __op_param3;
40
#ifdef USE_DIRECT_JUMP
41
int __op_jmp0, __op_jmp1;
42
#endif
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 volatile ("dcbst 0,%0" : : "r"(p) : "memory");
75
    }
76
    asm volatile ("sync" : : : "memory");
77
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
78
        asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
79
    }
80
    asm volatile ("sync" : : : "memory");
81
    asm volatile ("isync" : : : "memory");
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

    
116
typedef struct DisasContext {
117
    /* current insn context */
118
    int override; /* -1 if no override */
119
    int prefix;
120
    int aflag, dflag;
121
    uint8_t *pc; /* pc = eip + cs_base */
122
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
123
                   static state change (stop translation) */
124
    /* current block context */
125
    uint8_t *cs_base; /* base of CS segment */
126
    int code32; /* 32 bit code segment */
127
    int ss32;   /* 32 bit stack segment */
128
    int cc_op;  /* current CC operation */
129
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
130
    int f_st;   /* currently unused */
131
    int vm86;   /* vm86 mode */
132
    int cpl;
133
    int iopl;
134
    int tf;     /* TF cpu flag */
135
    TranslationBlock *tb;
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
typedef void (GenOpFunc3)(long, long, long);
200
                    
201
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
202
    [OT_BYTE] = {
203
        gen_op_movb_EAX_T0,
204
        gen_op_movb_ECX_T0,
205
        gen_op_movb_EDX_T0,
206
        gen_op_movb_EBX_T0,
207
        gen_op_movh_EAX_T0,
208
        gen_op_movh_ECX_T0,
209
        gen_op_movh_EDX_T0,
210
        gen_op_movh_EBX_T0,
211
    },
212
    [OT_WORD] = {
213
        gen_op_movw_EAX_T0,
214
        gen_op_movw_ECX_T0,
215
        gen_op_movw_EDX_T0,
216
        gen_op_movw_EBX_T0,
217
        gen_op_movw_ESP_T0,
218
        gen_op_movw_EBP_T0,
219
        gen_op_movw_ESI_T0,
220
        gen_op_movw_EDI_T0,
221
    },
222
    [OT_LONG] = {
223
        gen_op_movl_EAX_T0,
224
        gen_op_movl_ECX_T0,
225
        gen_op_movl_EDX_T0,
226
        gen_op_movl_EBX_T0,
227
        gen_op_movl_ESP_T0,
228
        gen_op_movl_EBP_T0,
229
        gen_op_movl_ESI_T0,
230
        gen_op_movl_EDI_T0,
231
    },
232
};
233

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
635

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

    
641

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

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

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

    
683

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

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

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

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

    
754
static GenOpFunc *gen_setcc_slow[8] = {
755
    gen_op_seto_T0_cc,
756
    gen_op_setb_T0_cc,
757
    gen_op_setz_T0_cc,
758
    gen_op_setbe_T0_cc,
759
    gen_op_sets_T0_cc,
760
    gen_op_setp_T0_cc,
761
    gen_op_setl_T0_cc,
762
    gen_op_setle_T0_cc,
763
};
764

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

    
798
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
799
    gen_op_fadd_ST0_FT0,
800
    gen_op_fmul_ST0_FT0,
801
    gen_op_fcom_ST0_FT0,
802
    gen_op_fcom_ST0_FT0,
803
    gen_op_fsub_ST0_FT0,
804
    gen_op_fsubr_ST0_FT0,
805
    gen_op_fdiv_ST0_FT0,
806
    gen_op_fdivr_ST0_FT0,
807
};
808

    
809
/* NOTE the exception in "r" op ordering */
810
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
811
    gen_op_fadd_STN_ST0,
812
    gen_op_fmul_STN_ST0,
813
    NULL,
814
    NULL,
815
    gen_op_fsubr_STN_ST0,
816
    gen_op_fsub_STN_ST0,
817
    gen_op_fdivr_STN_ST0,
818
    gen_op_fdiv_STN_ST0,
819
};
820

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

    
840
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
841
{
842
    gen_op_movl_T1_im(c);
843
    gen_op(s1, op, ot, d, OR_TMP1);
844
}
845

    
846
static void gen_inc(DisasContext *s1, int ot, int d, int c)
847
{
848
    if (d != OR_TMP0)
849
        gen_op_mov_TN_reg[ot][0][d]();
850
    if (s1->cc_op != CC_OP_DYNAMIC)
851
        gen_op_set_cc_op(s1->cc_op);
852
    if (c > 0) {
853
        gen_op_incl_T0_cc();
854
        s1->cc_op = CC_OP_INCB + ot;
855
    } else {
856
        gen_op_decl_T0_cc();
857
        s1->cc_op = CC_OP_DECB + ot;
858
    }
859
    if (d != OR_TMP0)
860
        gen_op_mov_reg_T0[ot][d]();
861
}
862

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

    
873
    gen_op_shift_T0_T1_cc[ot][op]();
874

    
875
    if (d != OR_TMP0)
876
        gen_op_mov_reg_T0[ot][d]();
877
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
878
}
879

    
880
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
881
{
882
    /* currently not optimized */
883
    gen_op_movl_T1_im(c);
884
    gen_shift(s1, op, ot, d, OR_TMP1);
885
}
886

    
887
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
888
{
889
    int havesib;
890
    int base, disp;
891
    int index;
892
    int scale;
893
    int opreg;
894
    int mod, rm, code, override, must_add_seg;
895

    
896
    override = s->override;
897
    must_add_seg = s->addseg;
898
    if (override >= 0)
899
        must_add_seg = 1;
900
    mod = (modrm >> 6) & 3;
901
    rm = modrm & 7;
902

    
903
    if (s->aflag) {
904

    
905
        havesib = 0;
906
        base = rm;
907
        index = 0;
908
        scale = 0;
909
        
910
        if (base == 4) {
911
            havesib = 1;
912
            code = ldub(s->pc++);
913
            scale = (code >> 6) & 3;
914
            index = (code >> 3) & 7;
915
            base = code & 7;
916
        }
917

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

    
1025
    opreg = OR_A0;
1026
    disp = 0;
1027
    *reg_ptr = opreg;
1028
    *offset_ptr = disp;
1029
}
1030

    
1031
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1032
   OR_TMP0 */
1033
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1034
{
1035
    int mod, rm, opreg, disp;
1036

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

    
1063
static inline uint32_t insn_get(DisasContext *s, int ot)
1064
{
1065
    uint32_t ret;
1066

    
1067
    switch(ot) {
1068
    case OT_BYTE:
1069
        ret = ldub(s->pc);
1070
        s->pc++;
1071
        break;
1072
    case OT_WORD:
1073
        ret = lduw(s->pc);
1074
        s->pc += 2;
1075
        break;
1076
    default:
1077
    case OT_LONG:
1078
        ret = ldl(s->pc);
1079
        s->pc += 4;
1080
        break;
1081
    }
1082
    return ret;
1083
}
1084

    
1085
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1086
{
1087
    TranslationBlock *tb;
1088
    int inv, jcc_op;
1089
    GenOpFunc3 *func;
1090

    
1091
    inv = b & 1;
1092
    jcc_op = (b >> 1) & 7;
1093
    switch(s->cc_op) {
1094
        /* we optimize the cmp/jcc case */
1095
    case CC_OP_SUBB:
1096
    case CC_OP_SUBW:
1097
    case CC_OP_SUBL:
1098
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1099
        break;
1100
        
1101
        /* some jumps are easy to compute */
1102
    case CC_OP_ADDB:
1103
    case CC_OP_ADDW:
1104
    case CC_OP_ADDL:
1105
    case CC_OP_ADCB:
1106
    case CC_OP_ADCW:
1107
    case CC_OP_ADCL:
1108
    case CC_OP_SBBB:
1109
    case CC_OP_SBBW:
1110
    case CC_OP_SBBL:
1111
    case CC_OP_LOGICB:
1112
    case CC_OP_LOGICW:
1113
    case CC_OP_LOGICL:
1114
    case CC_OP_INCB:
1115
    case CC_OP_INCW:
1116
    case CC_OP_INCL:
1117
    case CC_OP_DECB:
1118
    case CC_OP_DECW:
1119
    case CC_OP_DECL:
1120
    case CC_OP_SHLB:
1121
    case CC_OP_SHLW:
1122
    case CC_OP_SHLL:
1123
    case CC_OP_SARB:
1124
    case CC_OP_SARW:
1125
    case CC_OP_SARL:
1126
        switch(jcc_op) {
1127
        case JCC_Z:
1128
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1129
            break;
1130
        case JCC_S:
1131
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1132
            break;
1133
        default:
1134
            func = NULL;
1135
            break;
1136
        }
1137
        break;
1138
    default:
1139
        func = NULL;
1140
        break;
1141
    }
1142

    
1143
    if (s->cc_op != CC_OP_DYNAMIC)
1144
        gen_op_set_cc_op(s->cc_op);
1145

    
1146
    if (!func) {
1147
        gen_setcc_slow[jcc_op]();
1148
        func = gen_op_jcc;
1149
    }
1150
    
1151
    tb = s->tb;
1152
    if (!inv) {
1153
        func((long)tb, val, next_eip);
1154
    } else {
1155
        func((long)tb, next_eip, val);
1156
    }
1157
    s->is_jmp = 3;
1158
}
1159

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

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

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

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

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

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

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

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

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

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

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

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

    
1377
/* generate a jump to eip. No segment change must happen before as a
1378
   direct call to the next block may occur */
1379
static void gen_jmp(DisasContext *s, unsigned int eip)
1380
{
1381
    TranslationBlock *tb = s->tb;
1382

    
1383
    if (s->cc_op != CC_OP_DYNAMIC)
1384
        gen_op_set_cc_op(s->cc_op);
1385
    gen_op_jmp_tb_next((long)tb, eip);
1386
    s->is_jmp = 3;
1387
}
1388

    
1389
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1390
   is set to true if the instruction sets the PC (last instruction of
1391
   a basic block) */
1392
long disas_insn(DisasContext *s, uint8_t *pc_start)
1393
{
1394
    int b, prefixes, aflag, dflag;
1395
    int shift, ot;
1396
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1397
    unsigned int next_eip;
1398

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

    
1444
    if (prefixes & PREFIX_DATA)
1445
        dflag ^= 1;
1446
    if (prefixes & PREFIX_ADR)
1447
        aflag ^= 1;
1448

    
1449
    s->prefix = prefixes;
1450
    s->aflag = aflag;
1451
    s->dflag = dflag;
1452

    
1453
    /* lock generation */
1454
    if (prefixes & PREFIX_LOCK)
1455
        gen_op_lock();
1456

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

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

    
1526
    case 0x80: /* GRP1 */
1527
    case 0x81:
1528
    case 0x83:
1529
        {
1530
            int val;
1531

    
1532
            if ((b & 1) == 0)
1533
                ot = OT_BYTE;
1534
            else
1535
                ot = dflag ? OT_LONG : OT_WORD;
1536
            
1537
            modrm = ldub(s->pc++);
1538
            mod = (modrm >> 6) & 3;
1539
            rm = modrm & 7;
1540
            op = (modrm >> 3) & 7;
1541
            
1542
            if (mod != 3) {
1543
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1544
                gen_op_ld_T0_A0[ot]();
1545
                opreg = OR_TMP0;
1546
            } else {
1547
                opreg = rm + OR_EAX;
1548
            }
1549

    
1550
            switch(b) {
1551
            default:
1552
            case 0x80:
1553
            case 0x81:
1554
                val = insn_get(s, ot);
1555
                break;
1556
            case 0x83:
1557
                val = (int8_t)insn_get(s, OT_BYTE);
1558
                break;
1559
            }
1560

    
1561
            gen_opi(s, op, ot, opreg, val);
1562
            if (op != 7 && mod != 3) {
1563
                gen_op_st_T0_A0[ot]();
1564
            }
1565
        }
1566
        break;
1567

    
1568
        /**************************/
1569
        /* inc, dec, and other misc arith */
1570
    case 0x40 ... 0x47: /* inc Gv */
1571
        ot = dflag ? OT_LONG : OT_WORD;
1572
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1573
        break;
1574
    case 0x48 ... 0x4f: /* dec Gv */
1575
        ot = dflag ? OT_LONG : OT_WORD;
1576
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1577
        break;
1578
    case 0xf6: /* GRP3 */
1579
    case 0xf7:
1580
        if ((b & 1) == 0)
1581
            ot = OT_BYTE;
1582
        else
1583
            ot = dflag ? OT_LONG : OT_WORD;
1584

    
1585
        modrm = ldub(s->pc++);
1586
        mod = (modrm >> 6) & 3;
1587
        rm = modrm & 7;
1588
        op = (modrm >> 3) & 7;
1589
        if (mod != 3) {
1590
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1591
            gen_op_ld_T0_A0[ot]();
1592
        } else {
1593
            gen_op_mov_TN_reg[ot][0][rm]();
1594
        }
1595

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

    
1683
    case 0xfe: /* GRP4 */
1684
    case 0xff: /* GRP5 */
1685
        if ((b & 1) == 0)
1686
            ot = OT_BYTE;
1687
        else
1688
            ot = dflag ? OT_LONG : OT_WORD;
1689

    
1690
        modrm = ldub(s->pc++);
1691
        mod = (modrm >> 6) & 3;
1692
        rm = modrm & 7;
1693
        op = (modrm >> 3) & 7;
1694
        if (op >= 2 && b == 0xfe) {
1695
            goto illegal_op;
1696
        }
1697
        if (mod != 3) {
1698
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1699
            if (op != 3 && op != 5)
1700
                gen_op_ld_T0_A0[ot]();
1701
        } else {
1702
            gen_op_mov_TN_reg[ot][0][rm]();
1703
        }
1704

    
1705
        switch(op) {
1706
        case 0: /* inc 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 1: /* dec Ev */
1714
            gen_inc(s, ot, OR_TMP0, -1);
1715
            if (mod != 3)
1716
                gen_op_st_T0_A0[ot]();
1717
            else
1718
                gen_op_mov_reg_T0[ot][rm]();
1719
            break;
1720
        case 2: /* call Ev */
1721
            /* XXX: optimize if memory (no and is necessary) */
1722
            if (s->dflag == 0)
1723
                gen_op_andl_T0_ffff();
1724
            gen_op_jmp_T0();
1725
            next_eip = s->pc - s->cs_base;
1726
            gen_op_movl_T0_im(next_eip);
1727
            gen_push_T0(s);
1728
            s->is_jmp = 1;
1729
            break;
1730
        case 3: /* lcall Ev */
1731
            /* push return segment + offset */
1732
            gen_op_movl_T0_seg(R_CS);
1733
            gen_push_T0(s);
1734
            next_eip = s->pc - s->cs_base;
1735
            gen_op_movl_T0_im(next_eip);
1736
            gen_push_T0(s);
1737

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

    
1769
    case 0x84: /* test Ev, Gv */
1770
    case 0x85: 
1771
        if ((b & 1) == 0)
1772
            ot = OT_BYTE;
1773
        else
1774
            ot = dflag ? OT_LONG : OT_WORD;
1775

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

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

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

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

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

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

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

    
2265
            /* simpler op */
2266
            if (shift == 0) {
2267
                gen_shift(s, op, ot, opreg, OR_ECX);
2268
            } else {
2269
                if (shift == 2) {
2270
                    shift = ldub(s->pc++);
2271
                }
2272
                gen_shifti(s, op, ot, opreg, shift);
2273
            }
2274

    
2275
            if (mod != 3) {
2276
                gen_op_st_T0_A0[ot]();
2277
            }
2278
        }
2279
        break;
2280
    case 0xd0:
2281
    case 0xd1:
2282
        /* shift Ev,1 */
2283
        shift = 1;
2284
        goto grp2;
2285
    case 0xd2:
2286
    case 0xd3:
2287
        /* shift Ev,cl */
2288
        shift = 0;
2289
        goto grp2;
2290

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

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

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

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

    
2704
    case 0xa4: /* movsS */
2705
    case 0xa5:
2706
        if ((b & 1) == 0)
2707
            ot = OT_BYTE;
2708
        else
2709
            ot = dflag ? OT_LONG : OT_WORD;
2710

    
2711
        if (prefixes & PREFIX_REPZ) {
2712
            gen_string_ds(s, ot, gen_op_movs + 9);
2713
        } else {
2714
            gen_string_ds(s, ot, gen_op_movs);
2715
        }
2716
        break;
2717
        
2718
    case 0xaa: /* stosS */
2719
    case 0xab:
2720
        if ((b & 1) == 0)
2721
            ot = OT_BYTE;
2722
        else
2723
            ot = dflag ? OT_LONG : OT_WORD;
2724

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

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

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

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

    
2985
            ot = dflag ? OT_LONG : OT_WORD;
2986
            offset = insn_get(s, ot);
2987
            selector = insn_get(s, OT_WORD);
2988
            
2989
            /* push return segment + offset */
2990
            gen_op_movl_T0_seg(R_CS);
2991
            gen_push_T0(s);
2992
            next_eip = s->pc - s->cs_base;
2993
            gen_op_movl_T0_im(next_eip);
2994
            gen_push_T0(s);
2995

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

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

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

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

    
3382
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3383
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3384

    
3385
/* flags read by an operation */
3386
static uint16_t opc_read_flags[NB_OPS] = { 
3387
    [INDEX_op_aas] = CC_A,
3388
    [INDEX_op_aaa] = CC_A,
3389
    [INDEX_op_das] = CC_A | CC_C,
3390
    [INDEX_op_daa] = CC_A | CC_C,
3391

    
3392
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3393
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3394
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3395
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3396
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3397
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3398

    
3399
    /* subtle: due to the incl/decl implementation, C is used */
3400
    [INDEX_op_incl_T0_cc] = CC_C, 
3401
    [INDEX_op_decl_T0_cc] = CC_C,
3402

    
3403
    [INDEX_op_into] = CC_O,
3404

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3670

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

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

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

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

    
3707
#endif
3708

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

    
3715
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3716

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

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

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

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

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

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

    
3796
    *gen_opc_ptr = INDEX_op_end;
3797

    
3798
#ifdef DEBUG_DISAS
3799
    if (loglevel) {
3800
        fprintf(logfile, "----------------\n");
3801
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3802
        disas(logfile, pc_start, pc_ptr - pc_start,
3803
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3804
        fprintf(logfile, "\n");
3805

    
3806
        fprintf(logfile, "OP:\n");
3807
        dump_ops(gen_opc_buf, gen_opparam_buf);
3808
        fprintf(logfile, "\n");
3809
    }
3810
#endif
3811

    
3812
    /* optimize flag computations */
3813
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3814

    
3815
#ifdef DEBUG_DISAS
3816
    if (loglevel) {
3817
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3818
        dump_ops(gen_opc_buf, gen_opparam_buf);
3819
        fprintf(logfile, "\n");
3820
    }
3821
#endif
3822

    
3823
    /* generate machine code */
3824
    tb->tb_next_offset[0] = 0xffff;
3825
    tb->tb_next_offset[1] = 0xffff;
3826
    gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3827
#ifdef USE_DIRECT_JUMP
3828
                                tb->tb_jmp_offset,
3829
#else
3830
                                NULL,
3831
#endif
3832
                                gen_opc_buf, gen_opparam_buf);
3833
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3834

    
3835
    *gen_code_size_ptr = gen_code_size;
3836
    *code_size_ptr = pc_ptr - pc_start;
3837
#ifdef DEBUG_DISAS
3838
    if (loglevel) {
3839
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3840
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3841
        fprintf(logfile, "\n");
3842
        fflush(logfile);
3843
    }
3844
#endif
3845
    return 0;
3846
}
3847

    
3848
CPUX86State *cpu_x86_init(void)
3849
{
3850
    CPUX86State *env;
3851
    int i;
3852
    static int inited;
3853

    
3854
    cpu_x86_tblocks_init();
3855

    
3856
    env = malloc(sizeof(CPUX86State));
3857
    if (!env)
3858
        return NULL;
3859
    memset(env, 0, sizeof(CPUX86State));
3860
    /* basic FPU init */
3861
    for(i = 0;i < 8; i++)
3862
        env->fptags[i] = 1;
3863
    env->fpuc = 0x37f;
3864
    /* flags setup : we activate the IRQs by default as in user mode */
3865
    env->eflags = 0x2 | IF_MASK;
3866

    
3867
    /* init various static tables */
3868
    if (!inited) {
3869
        inited = 1;
3870
        optimize_flags_init();
3871
        page_init();
3872
    }
3873
    return env;
3874
}
3875

    
3876
void cpu_x86_close(CPUX86State *env)
3877
{
3878
    free(env);
3879
}
3880

    
3881
static const char *cc_op_str[] = {
3882
    "DYNAMIC",
3883
    "EFLAGS",
3884
    "MUL",
3885
    "ADDB",
3886
    "ADDW",
3887
    "ADDL",
3888
    "ADCB",
3889
    "ADCW",
3890
    "ADCL",
3891
    "SUBB",
3892
    "SUBW",
3893
    "SUBL",
3894
    "SBBB",
3895
    "SBBW",
3896
    "SBBL",
3897
    "LOGICB",
3898
    "LOGICW",
3899
    "LOGICL",
3900
    "INCB",
3901
    "INCW",
3902
    "INCL",
3903
    "DECB",
3904
    "DECW",
3905
    "DECL",
3906
    "SHLB",
3907
    "SHLW",
3908
    "SHLL",
3909
    "SARB",
3910
    "SARW",
3911
    "SARL",
3912
};
3913

    
3914
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3915
{
3916
    int eflags;
3917
    char cc_op_name[32];
3918

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