Statistics
| Branch: | Revision:

root / translate-i386.c @ 5a91de8c

History | View | Annotate | Download (109.6 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, copy_size) 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, unsigned int cur_eip)
1219
{
1220
    if (!s->vm86)
1221
        gen_op_movl_seg_T0(seg_reg, cur_eip);
1222
    else
1223
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]),
1224
                              offsetof(CPUX86State,seg_cache[seg_reg].base));
1225
    if (!s->addseg && seg_reg < R_FS)
1226
        s->is_jmp = 2; /* abort translation because the register may
1227
                          have a non zero base */
1228
}
1229

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

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

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

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

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

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

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

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

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

    
1381
/* an interrupt is different from an exception because of the
1382
   priviledge checks */
1383
static void gen_interrupt(DisasContext *s, int intno, 
1384
                          unsigned int cur_eip, unsigned int next_eip)
1385
{
1386
    if (s->cc_op != CC_OP_DYNAMIC)
1387
        gen_op_set_cc_op(s->cc_op);
1388
    gen_op_jmp_im(cur_eip);
1389
    gen_op_raise_interrupt(intno, next_eip);
1390
    s->is_jmp = 1;
1391
}
1392

    
1393
/* generate a jump to eip. No segment change must happen before as a
1394
   direct call to the next block may occur */
1395
static void gen_jmp(DisasContext *s, unsigned int eip)
1396
{
1397
    TranslationBlock *tb = s->tb;
1398

    
1399
    if (s->cc_op != CC_OP_DYNAMIC)
1400
        gen_op_set_cc_op(s->cc_op);
1401
    gen_op_jmp_tb_next((long)tb, eip);
1402
    s->is_jmp = 3;
1403
}
1404

    
1405
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1406
   is set to true if the instruction sets the PC (last instruction of
1407
   a basic block) */
1408
long disas_insn(DisasContext *s, uint8_t *pc_start)
1409
{
1410
    int b, prefixes, aflag, dflag;
1411
    int shift, ot;
1412
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1413
    unsigned int next_eip;
1414

    
1415
    s->pc = pc_start;
1416
    prefixes = 0;
1417
    aflag = s->code32;
1418
    dflag = s->code32;
1419
    s->override = -1;
1420
 next_byte:
1421
    b = ldub(s->pc);
1422
    s->pc++;
1423
    /* check prefixes */
1424
    switch (b) {
1425
    case 0xf3:
1426
        prefixes |= PREFIX_REPZ;
1427
        goto next_byte;
1428
    case 0xf2:
1429
        prefixes |= PREFIX_REPNZ;
1430
        goto next_byte;
1431
    case 0xf0:
1432
        prefixes |= PREFIX_LOCK;
1433
        goto next_byte;
1434
    case 0x2e:
1435
        s->override = R_CS;
1436
        goto next_byte;
1437
    case 0x36:
1438
        s->override = R_SS;
1439
        goto next_byte;
1440
    case 0x3e:
1441
        s->override = R_DS;
1442
        goto next_byte;
1443
    case 0x26:
1444
        s->override = R_ES;
1445
        goto next_byte;
1446
    case 0x64:
1447
        s->override = R_FS;
1448
        goto next_byte;
1449
    case 0x65:
1450
        s->override = R_GS;
1451
        goto next_byte;
1452
    case 0x66:
1453
        prefixes |= PREFIX_DATA;
1454
        goto next_byte;
1455
    case 0x67:
1456
        prefixes |= PREFIX_ADR;
1457
        goto next_byte;
1458
    }
1459

    
1460
    if (prefixes & PREFIX_DATA)
1461
        dflag ^= 1;
1462
    if (prefixes & PREFIX_ADR)
1463
        aflag ^= 1;
1464

    
1465
    s->prefix = prefixes;
1466
    s->aflag = aflag;
1467
    s->dflag = dflag;
1468

    
1469
    /* lock generation */
1470
    if (prefixes & PREFIX_LOCK)
1471
        gen_op_lock();
1472

    
1473
    /* now check op code */
1474
 reswitch:
1475
    switch(b) {
1476
    case 0x0f:
1477
        /**************************/
1478
        /* extended op code */
1479
        b = ldub(s->pc++) | 0x100;
1480
        goto reswitch;
1481
        
1482
        /**************************/
1483
        /* arith & logic */
1484
    case 0x00 ... 0x05:
1485
    case 0x08 ... 0x0d:
1486
    case 0x10 ... 0x15:
1487
    case 0x18 ... 0x1d:
1488
    case 0x20 ... 0x25:
1489
    case 0x28 ... 0x2d:
1490
    case 0x30 ... 0x35:
1491
    case 0x38 ... 0x3d:
1492
        {
1493
            int op, f, val;
1494
            op = (b >> 3) & 7;
1495
            f = (b >> 1) & 3;
1496

    
1497
            if ((b & 1) == 0)
1498
                ot = OT_BYTE;
1499
            else
1500
                ot = dflag ? OT_LONG : OT_WORD;
1501
            
1502
            switch(f) {
1503
            case 0: /* OP Ev, Gv */
1504
                modrm = ldub(s->pc++);
1505
                reg = ((modrm >> 3) & 7) + OR_EAX;
1506
                mod = (modrm >> 6) & 3;
1507
                rm = modrm & 7;
1508
                if (mod != 3) {
1509
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1510
                    gen_op_ld_T0_A0[ot]();
1511
                    opreg = OR_TMP0;
1512
                } else {
1513
                    opreg = OR_EAX + rm;
1514
                }
1515
                gen_op(s, op, ot, opreg, reg);
1516
                if (mod != 3 && op != 7) {
1517
                    gen_op_st_T0_A0[ot]();
1518
                }
1519
                break;
1520
            case 1: /* OP Gv, Ev */
1521
                modrm = ldub(s->pc++);
1522
                mod = (modrm >> 6) & 3;
1523
                reg = ((modrm >> 3) & 7) + OR_EAX;
1524
                rm = modrm & 7;
1525
                if (mod != 3) {
1526
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1527
                    gen_op_ld_T1_A0[ot]();
1528
                    opreg = OR_TMP1;
1529
                } else {
1530
                    opreg = OR_EAX + rm;
1531
                }
1532
                gen_op(s, op, ot, reg, opreg);
1533
                break;
1534
            case 2: /* OP A, Iv */
1535
                val = insn_get(s, ot);
1536
                gen_opi(s, op, ot, OR_EAX, val);
1537
                break;
1538
            }
1539
        }
1540
        break;
1541

    
1542
    case 0x80: /* GRP1 */
1543
    case 0x81:
1544
    case 0x83:
1545
        {
1546
            int val;
1547

    
1548
            if ((b & 1) == 0)
1549
                ot = OT_BYTE;
1550
            else
1551
                ot = dflag ? OT_LONG : OT_WORD;
1552
            
1553
            modrm = ldub(s->pc++);
1554
            mod = (modrm >> 6) & 3;
1555
            rm = modrm & 7;
1556
            op = (modrm >> 3) & 7;
1557
            
1558
            if (mod != 3) {
1559
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1560
                gen_op_ld_T0_A0[ot]();
1561
                opreg = OR_TMP0;
1562
            } else {
1563
                opreg = rm + OR_EAX;
1564
            }
1565

    
1566
            switch(b) {
1567
            default:
1568
            case 0x80:
1569
            case 0x81:
1570
                val = insn_get(s, ot);
1571
                break;
1572
            case 0x83:
1573
                val = (int8_t)insn_get(s, OT_BYTE);
1574
                break;
1575
            }
1576

    
1577
            gen_opi(s, op, ot, opreg, val);
1578
            if (op != 7 && mod != 3) {
1579
                gen_op_st_T0_A0[ot]();
1580
            }
1581
        }
1582
        break;
1583

    
1584
        /**************************/
1585
        /* inc, dec, and other misc arith */
1586
    case 0x40 ... 0x47: /* inc Gv */
1587
        ot = dflag ? OT_LONG : OT_WORD;
1588
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1589
        break;
1590
    case 0x48 ... 0x4f: /* dec Gv */
1591
        ot = dflag ? OT_LONG : OT_WORD;
1592
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1593
        break;
1594
    case 0xf6: /* GRP3 */
1595
    case 0xf7:
1596
        if ((b & 1) == 0)
1597
            ot = OT_BYTE;
1598
        else
1599
            ot = dflag ? OT_LONG : OT_WORD;
1600

    
1601
        modrm = ldub(s->pc++);
1602
        mod = (modrm >> 6) & 3;
1603
        rm = modrm & 7;
1604
        op = (modrm >> 3) & 7;
1605
        if (mod != 3) {
1606
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1607
            gen_op_ld_T0_A0[ot]();
1608
        } else {
1609
            gen_op_mov_TN_reg[ot][0][rm]();
1610
        }
1611

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

    
1699
    case 0xfe: /* GRP4 */
1700
    case 0xff: /* GRP5 */
1701
        if ((b & 1) == 0)
1702
            ot = OT_BYTE;
1703
        else
1704
            ot = dflag ? OT_LONG : OT_WORD;
1705

    
1706
        modrm = ldub(s->pc++);
1707
        mod = (modrm >> 6) & 3;
1708
        rm = modrm & 7;
1709
        op = (modrm >> 3) & 7;
1710
        if (op >= 2 && b == 0xfe) {
1711
            goto illegal_op;
1712
        }
1713
        if (mod != 3) {
1714
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1715
            if (op != 3 && op != 5)
1716
                gen_op_ld_T0_A0[ot]();
1717
        } else {
1718
            gen_op_mov_TN_reg[ot][0][rm]();
1719
        }
1720

    
1721
        switch(op) {
1722
        case 0: /* inc Ev */
1723
            gen_inc(s, ot, OR_TMP0, 1);
1724
            if (mod != 3)
1725
                gen_op_st_T0_A0[ot]();
1726
            else
1727
                gen_op_mov_reg_T0[ot][rm]();
1728
            break;
1729
        case 1: /* dec Ev */
1730
            gen_inc(s, ot, OR_TMP0, -1);
1731
            if (mod != 3)
1732
                gen_op_st_T0_A0[ot]();
1733
            else
1734
                gen_op_mov_reg_T0[ot][rm]();
1735
            break;
1736
        case 2: /* call Ev */
1737
            /* XXX: optimize if memory (no and is necessary) */
1738
            if (s->dflag == 0)
1739
                gen_op_andl_T0_ffff();
1740
            gen_op_jmp_T0();
1741
            next_eip = s->pc - s->cs_base;
1742
            gen_op_movl_T0_im(next_eip);
1743
            gen_push_T0(s);
1744
            s->is_jmp = 1;
1745
            break;
1746
        case 3: /* lcall Ev */
1747
            /* push return segment + offset */
1748
            gen_op_movl_T0_seg(R_CS);
1749
            gen_push_T0(s);
1750
            next_eip = s->pc - s->cs_base;
1751
            gen_op_movl_T0_im(next_eip);
1752
            gen_push_T0(s);
1753

    
1754
            gen_op_ld_T1_A0[ot]();
1755
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1756
            gen_op_lduw_T0_A0();
1757
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1758
            gen_op_movl_T0_T1();
1759
            gen_op_jmp_T0();
1760
            s->is_jmp = 1;
1761
            break;
1762
        case 4: /* jmp Ev */
1763
            if (s->dflag == 0)
1764
                gen_op_andl_T0_ffff();
1765
            gen_op_jmp_T0();
1766
            s->is_jmp = 1;
1767
            break;
1768
        case 5: /* ljmp Ev */
1769
            gen_op_ld_T1_A0[ot]();
1770
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1771
            gen_op_lduw_T0_A0();
1772
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1773
            gen_op_movl_T0_T1();
1774
            gen_op_jmp_T0();
1775
            s->is_jmp = 1;
1776
            break;
1777
        case 6: /* push Ev */
1778
            gen_push_T0(s);
1779
            break;
1780
        default:
1781
            goto illegal_op;
1782
        }
1783
        break;
1784

    
1785
    case 0x84: /* test Ev, Gv */
1786
    case 0x85: 
1787
        if ((b & 1) == 0)
1788
            ot = OT_BYTE;
1789
        else
1790
            ot = dflag ? OT_LONG : OT_WORD;
1791

    
1792
        modrm = ldub(s->pc++);
1793
        mod = (modrm >> 6) & 3;
1794
        rm = modrm & 7;
1795
        reg = (modrm >> 3) & 7;
1796
        
1797
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1798
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1799
        gen_op_testl_T0_T1_cc();
1800
        s->cc_op = CC_OP_LOGICB + ot;
1801
        break;
1802
        
1803
    case 0xa8: /* test eAX, Iv */
1804
    case 0xa9:
1805
        if ((b & 1) == 0)
1806
            ot = OT_BYTE;
1807
        else
1808
            ot = dflag ? OT_LONG : OT_WORD;
1809
        val = insn_get(s, ot);
1810

    
1811
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1812
        gen_op_movl_T1_im(val);
1813
        gen_op_testl_T0_T1_cc();
1814
        s->cc_op = CC_OP_LOGICB + ot;
1815
        break;
1816
        
1817
    case 0x98: /* CWDE/CBW */
1818
        if (dflag)
1819
            gen_op_movswl_EAX_AX();
1820
        else
1821
            gen_op_movsbw_AX_AL();
1822
        break;
1823
    case 0x99: /* CDQ/CWD */
1824
        if (dflag)
1825
            gen_op_movslq_EDX_EAX();
1826
        else
1827
            gen_op_movswl_DX_AX();
1828
        break;
1829
    case 0x1af: /* imul Gv, Ev */
1830
    case 0x69: /* imul Gv, Ev, I */
1831
    case 0x6b:
1832
        ot = dflag ? OT_LONG : OT_WORD;
1833
        modrm = ldub(s->pc++);
1834
        reg = ((modrm >> 3) & 7) + OR_EAX;
1835
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1836
        if (b == 0x69) {
1837
            val = insn_get(s, ot);
1838
            gen_op_movl_T1_im(val);
1839
        } else if (b == 0x6b) {
1840
            val = insn_get(s, OT_BYTE);
1841
            gen_op_movl_T1_im(val);
1842
        } else {
1843
            gen_op_mov_TN_reg[ot][1][reg]();
1844
        }
1845

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

    
1999
        /**************************/
2000
        /* mov */
2001
    case 0x88:
2002
    case 0x89: /* mov Gv, Ev */
2003
        if ((b & 1) == 0)
2004
            ot = OT_BYTE;
2005
        else
2006
            ot = dflag ? OT_LONG : OT_WORD;
2007
        modrm = ldub(s->pc++);
2008
        reg = (modrm >> 3) & 7;
2009
        
2010
        /* generate a generic store */
2011
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2012
        break;
2013
    case 0xc6:
2014
    case 0xc7: /* mov Ev, Iv */
2015
        if ((b & 1) == 0)
2016
            ot = OT_BYTE;
2017
        else
2018
            ot = dflag ? OT_LONG : OT_WORD;
2019
        modrm = ldub(s->pc++);
2020
        mod = (modrm >> 6) & 3;
2021
        if (mod != 3)
2022
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2023
        val = insn_get(s, ot);
2024
        gen_op_movl_T0_im(val);
2025
        if (mod != 3)
2026
            gen_op_st_T0_A0[ot]();
2027
        else
2028
            gen_op_mov_reg_T0[ot][modrm & 7]();
2029
        break;
2030
    case 0x8a:
2031
    case 0x8b: /* mov Ev, Gv */
2032
        if ((b & 1) == 0)
2033
            ot = OT_BYTE;
2034
        else
2035
            ot = dflag ? OT_LONG : OT_WORD;
2036
        modrm = ldub(s->pc++);
2037
        reg = (modrm >> 3) & 7;
2038
        
2039
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2040
        gen_op_mov_reg_T0[ot][reg]();
2041
        break;
2042
    case 0x8e: /* mov seg, Gv */
2043
        ot = dflag ? OT_LONG : OT_WORD;
2044
        modrm = ldub(s->pc++);
2045
        reg = (modrm >> 3) & 7;
2046
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2047
        if (reg >= 6 || reg == R_CS)
2048
            goto illegal_op;
2049
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2050
        break;
2051
    case 0x8c: /* mov Gv, seg */
2052
        ot = dflag ? OT_LONG : OT_WORD;
2053
        modrm = ldub(s->pc++);
2054
        reg = (modrm >> 3) & 7;
2055
        if (reg >= 6)
2056
            goto illegal_op;
2057
        gen_op_movl_T0_seg(reg);
2058
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2059
        break;
2060

    
2061
    case 0x1b6: /* movzbS Gv, Eb */
2062
    case 0x1b7: /* movzwS Gv, Eb */
2063
    case 0x1be: /* movsbS Gv, Eb */
2064
    case 0x1bf: /* movswS Gv, Eb */
2065
        {
2066
            int d_ot;
2067
            /* d_ot is the size of destination */
2068
            d_ot = dflag + OT_WORD;
2069
            /* ot is the size of source */
2070
            ot = (b & 1) + OT_BYTE;
2071
            modrm = ldub(s->pc++);
2072
            reg = ((modrm >> 3) & 7) + OR_EAX;
2073
            mod = (modrm >> 6) & 3;
2074
            rm = modrm & 7;
2075
            
2076
            if (mod == 3) {
2077
                gen_op_mov_TN_reg[ot][0][rm]();
2078
                switch(ot | (b & 8)) {
2079
                case OT_BYTE:
2080
                    gen_op_movzbl_T0_T0();
2081
                    break;
2082
                case OT_BYTE | 8:
2083
                    gen_op_movsbl_T0_T0();
2084
                    break;
2085
                case OT_WORD:
2086
                    gen_op_movzwl_T0_T0();
2087
                    break;
2088
                default:
2089
                case OT_WORD | 8:
2090
                    gen_op_movswl_T0_T0();
2091
                    break;
2092
                }
2093
                gen_op_mov_reg_T0[d_ot][reg]();
2094
            } else {
2095
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2096
                if (b & 8) {
2097
                    gen_op_lds_T0_A0[ot]();
2098
                } else {
2099
                    gen_op_ldu_T0_A0[ot]();
2100
                }
2101
                gen_op_mov_reg_T0[d_ot][reg]();
2102
            }
2103
        }
2104
        break;
2105

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

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

    
2281
            /* simpler op */
2282
            if (shift == 0) {
2283
                gen_shift(s, op, ot, opreg, OR_ECX);
2284
            } else {
2285
                if (shift == 2) {
2286
                    shift = ldub(s->pc++);
2287
                }
2288
                gen_shifti(s, op, ot, opreg, shift);
2289
            }
2290

    
2291
            if (mod != 3) {
2292
                gen_op_st_T0_A0[ot]();
2293
            }
2294
        }
2295
        break;
2296
    case 0xd0:
2297
    case 0xd1:
2298
        /* shift Ev,1 */
2299
        shift = 1;
2300
        goto grp2;
2301
    case 0xd2:
2302
    case 0xd3:
2303
        /* shift Ev,cl */
2304
        shift = 0;
2305
        goto grp2;
2306

    
2307
    case 0x1a4: /* shld imm */
2308
        op = 0;
2309
        shift = 1;
2310
        goto do_shiftd;
2311
    case 0x1a5: /* shld cl */
2312
        op = 0;
2313
        shift = 0;
2314
        goto do_shiftd;
2315
    case 0x1ac: /* shrd imm */
2316
        op = 1;
2317
        shift = 1;
2318
        goto do_shiftd;
2319
    case 0x1ad: /* shrd cl */
2320
        op = 1;
2321
        shift = 0;
2322
    do_shiftd:
2323
        ot = dflag ? OT_LONG : OT_WORD;
2324
        modrm = ldub(s->pc++);
2325
        mod = (modrm >> 6) & 3;
2326
        rm = modrm & 7;
2327
        reg = (modrm >> 3) & 7;
2328
        
2329
        if (mod != 3) {
2330
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2331
            gen_op_ld_T0_A0[ot]();
2332
        } else {
2333
            gen_op_mov_TN_reg[ot][0][rm]();
2334
        }
2335
        gen_op_mov_TN_reg[ot][1][reg]();
2336
        
2337
        if (shift) {
2338
            val = ldub(s->pc++);
2339
            val &= 0x1f;
2340
            if (val) {
2341
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2342
                if (op == 0 && ot != OT_WORD)
2343
                    s->cc_op = CC_OP_SHLB + ot;
2344
                else
2345
                    s->cc_op = CC_OP_SARB + ot;
2346
            }
2347
        } else {
2348
            if (s->cc_op != CC_OP_DYNAMIC)
2349
                gen_op_set_cc_op(s->cc_op);
2350
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2351
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2352
        }
2353
        if (mod != 3) {
2354
            gen_op_st_T0_A0[ot]();
2355
        } else {
2356
            gen_op_mov_reg_T0[ot][rm]();
2357
        }
2358
        break;
2359

    
2360
        /************************/
2361
        /* floats */
2362
    case 0xd8 ... 0xdf: 
2363
        modrm = ldub(s->pc++);
2364
        mod = (modrm >> 6) & 3;
2365
        rm = modrm & 7;
2366
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2367
        
2368
        if (mod != 3) {
2369
            /* memory op */
2370
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2371
            switch(op) {
2372
            case 0x00 ... 0x07: /* fxxxs */
2373
            case 0x10 ... 0x17: /* fixxxl */
2374
            case 0x20 ... 0x27: /* fxxxl */
2375
            case 0x30 ... 0x37: /* fixxx */
2376
                {
2377
                    int op1;
2378
                    op1 = op & 7;
2379

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

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

    
2720
    case 0xa4: /* movsS */
2721
    case 0xa5:
2722
        if ((b & 1) == 0)
2723
            ot = OT_BYTE;
2724
        else
2725
            ot = dflag ? OT_LONG : OT_WORD;
2726

    
2727
        if (prefixes & PREFIX_REPZ) {
2728
            gen_string_ds(s, ot, gen_op_movs + 9);
2729
        } else {
2730
            gen_string_ds(s, ot, gen_op_movs);
2731
        }
2732
        break;
2733
        
2734
    case 0xaa: /* stosS */
2735
    case 0xab:
2736
        if ((b & 1) == 0)
2737
            ot = OT_BYTE;
2738
        else
2739
            ot = dflag ? OT_LONG : OT_WORD;
2740

    
2741
        if (prefixes & PREFIX_REPZ) {
2742
            gen_string_es(s, ot, gen_op_stos + 9);
2743
        } else {
2744
            gen_string_es(s, ot, gen_op_stos);
2745
        }
2746
        break;
2747
    case 0xac: /* lodsS */
2748
    case 0xad:
2749
        if ((b & 1) == 0)
2750
            ot = OT_BYTE;
2751
        else
2752
            ot = dflag ? OT_LONG : OT_WORD;
2753
        if (prefixes & PREFIX_REPZ) {
2754
            gen_string_ds(s, ot, gen_op_lods + 9);
2755
        } else {
2756
            gen_string_ds(s, ot, gen_op_lods);
2757
        }
2758
        break;
2759
    case 0xae: /* scasS */
2760
    case 0xaf:
2761
        if ((b & 1) == 0)
2762
            ot = OT_BYTE;
2763
        else
2764
                ot = dflag ? OT_LONG : OT_WORD;
2765
        if (prefixes & PREFIX_REPNZ) {
2766
            if (s->cc_op != CC_OP_DYNAMIC)
2767
                gen_op_set_cc_op(s->cc_op);
2768
            gen_string_es(s, ot, gen_op_scas + 9 * 2);
2769
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2770
        } else if (prefixes & PREFIX_REPZ) {
2771
            if (s->cc_op != CC_OP_DYNAMIC)
2772
                gen_op_set_cc_op(s->cc_op);
2773
            gen_string_es(s, ot, gen_op_scas + 9);
2774
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2775
        } else {
2776
            gen_string_es(s, ot, gen_op_scas);
2777
            s->cc_op = CC_OP_SUBB + ot;
2778
        }
2779
        break;
2780

    
2781
    case 0xa6: /* cmpsS */
2782
    case 0xa7:
2783
        if ((b & 1) == 0)
2784
            ot = OT_BYTE;
2785
        else
2786
            ot = dflag ? OT_LONG : OT_WORD;
2787
        if (prefixes & PREFIX_REPNZ) {
2788
            if (s->cc_op != CC_OP_DYNAMIC)
2789
                gen_op_set_cc_op(s->cc_op);
2790
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2791
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2792
        } else if (prefixes & PREFIX_REPZ) {
2793
            if (s->cc_op != CC_OP_DYNAMIC)
2794
                gen_op_set_cc_op(s->cc_op);
2795
            gen_string_ds(s, ot, gen_op_cmps + 9);
2796
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2797
        } else {
2798
            gen_string_ds(s, ot, gen_op_cmps);
2799
            s->cc_op = CC_OP_SUBB + ot;
2800
        }
2801
        break;
2802
    case 0x6c: /* insS */
2803
    case 0x6d:
2804
        if (s->cpl > s->iopl || s->vm86) {
2805
            /* NOTE: even for (E)CX = 0 the exception is raised */
2806
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2807
        } else {
2808
            if ((b & 1) == 0)
2809
                ot = OT_BYTE;
2810
            else
2811
                ot = dflag ? OT_LONG : OT_WORD;
2812
            if (prefixes & PREFIX_REPZ) {
2813
                gen_string_es(s, ot, gen_op_ins + 9);
2814
            } else {
2815
                gen_string_es(s, ot, gen_op_ins);
2816
            }
2817
        }
2818
        break;
2819
    case 0x6e: /* outsS */
2820
    case 0x6f:
2821
        if (s->cpl > s->iopl || s->vm86) {
2822
            /* NOTE: even for (E)CX = 0 the exception is raised */
2823
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2824
        } else {
2825
            if ((b & 1) == 0)
2826
                ot = OT_BYTE;
2827
            else
2828
                ot = dflag ? OT_LONG : OT_WORD;
2829
            if (prefixes & PREFIX_REPZ) {
2830
                gen_string_ds(s, ot, gen_op_outs + 9);
2831
            } else {
2832
                gen_string_ds(s, ot, gen_op_outs);
2833
            }
2834
        }
2835
        break;
2836

    
2837
        /************************/
2838
        /* port I/O */
2839
    case 0xe4:
2840
    case 0xe5:
2841
        if (s->cpl > s->iopl || s->vm86) {
2842
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2843
        } else {
2844
            if ((b & 1) == 0)
2845
                ot = OT_BYTE;
2846
            else
2847
                ot = dflag ? OT_LONG : OT_WORD;
2848
            val = ldub(s->pc++);
2849
            gen_op_movl_T0_im(val);
2850
            gen_op_in[ot]();
2851
            gen_op_mov_reg_T1[ot][R_EAX]();
2852
        }
2853
        break;
2854
    case 0xe6:
2855
    case 0xe7:
2856
        if (s->cpl > s->iopl || s->vm86) {
2857
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2858
        } else {
2859
            if ((b & 1) == 0)
2860
                ot = OT_BYTE;
2861
            else
2862
                ot = dflag ? OT_LONG : OT_WORD;
2863
            val = ldub(s->pc++);
2864
            gen_op_movl_T0_im(val);
2865
            gen_op_mov_TN_reg[ot][1][R_EAX]();
2866
            gen_op_out[ot]();
2867
        }
2868
        break;
2869
    case 0xec:
2870
    case 0xed:
2871
        if (s->cpl > s->iopl || s->vm86) {
2872
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2873
        } else {
2874
            if ((b & 1) == 0)
2875
                ot = OT_BYTE;
2876
            else
2877
                ot = dflag ? OT_LONG : OT_WORD;
2878
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2879
            gen_op_in[ot]();
2880
            gen_op_mov_reg_T1[ot][R_EAX]();
2881
        }
2882
        break;
2883
    case 0xee:
2884
    case 0xef:
2885
        if (s->cpl > s->iopl || s->vm86) {
2886
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2887
        } else {
2888
            if ((b & 1) == 0)
2889
                ot = OT_BYTE;
2890
            else
2891
                ot = dflag ? OT_LONG : OT_WORD;
2892
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2893
            gen_op_mov_TN_reg[ot][1][R_EAX]();
2894
            gen_op_out[ot]();
2895
        }
2896
        break;
2897

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

    
3001
            ot = dflag ? OT_LONG : OT_WORD;
3002
            offset = insn_get(s, ot);
3003
            selector = insn_get(s, OT_WORD);
3004
            
3005
            /* push return segment + offset */
3006
            gen_op_movl_T0_seg(R_CS);
3007
            gen_push_T0(s);
3008
            next_eip = s->pc - s->cs_base;
3009
            gen_op_movl_T0_im(next_eip);
3010
            gen_push_T0(s);
3011

    
3012
            /* change cs and pc */
3013
            gen_op_movl_T0_im(selector);
3014
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3015
            gen_op_jmp_im((unsigned long)offset);
3016
            s->is_jmp = 1;
3017
        }
3018
        break;
3019
    case 0xe9: /* jmp */
3020
        ot = dflag ? OT_LONG : OT_WORD;
3021
        val = insn_get(s, ot);
3022
        val += s->pc - s->cs_base;
3023
        if (s->dflag == 0)
3024
            val = val & 0xffff;
3025
        gen_jmp(s, val);
3026
        break;
3027
    case 0xea: /* ljmp im */
3028
        {
3029
            unsigned int selector, offset;
3030

    
3031
            ot = dflag ? OT_LONG : OT_WORD;
3032
            offset = insn_get(s, ot);
3033
            selector = insn_get(s, OT_WORD);
3034
            
3035
            /* change cs and pc */
3036
            gen_op_movl_T0_im(selector);
3037
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3038
            gen_op_jmp_im((unsigned long)offset);
3039
            s->is_jmp = 1;
3040
        }
3041
        break;
3042
    case 0xeb: /* jmp Jb */
3043
        val = (int8_t)insn_get(s, OT_BYTE);
3044
        val += s->pc - s->cs_base;
3045
        if (s->dflag == 0)
3046
            val = val & 0xffff;
3047
        gen_jmp(s, val);
3048
        break;
3049
    case 0x70 ... 0x7f: /* jcc Jb */
3050
        val = (int8_t)insn_get(s, OT_BYTE);
3051
        goto do_jcc;
3052
    case 0x180 ... 0x18f: /* jcc Jv */
3053
        if (dflag) {
3054
            val = insn_get(s, OT_LONG);
3055
        } else {
3056
            val = (int16_t)insn_get(s, OT_WORD); 
3057
        }
3058
    do_jcc:
3059
        next_eip = s->pc - s->cs_base;
3060
        val += next_eip;
3061
        if (s->dflag == 0)
3062
            val &= 0xffff;
3063
        gen_jcc(s, b, val, next_eip);
3064
        break;
3065

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

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

    
3399
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3400
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3401

    
3402
/* flags read by an operation */
3403
static uint16_t opc_read_flags[NB_OPS] = { 
3404
    [INDEX_op_aas] = CC_A,
3405
    [INDEX_op_aaa] = CC_A,
3406
    [INDEX_op_das] = CC_A | CC_C,
3407
    [INDEX_op_daa] = CC_A | CC_C,
3408

    
3409
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3410
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3411
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3412
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3413
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3414
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3415

    
3416
    /* subtle: due to the incl/decl implementation, C is used */
3417
    [INDEX_op_incl_T0_cc] = CC_C, 
3418
    [INDEX_op_decl_T0_cc] = CC_C,
3419

    
3420
    [INDEX_op_into] = CC_O,
3421

    
3422
    [INDEX_op_jb_subb] = CC_C,
3423
    [INDEX_op_jb_subw] = CC_C,
3424
    [INDEX_op_jb_subl] = CC_C,
3425

    
3426
    [INDEX_op_jz_subb] = CC_Z,
3427
    [INDEX_op_jz_subw] = CC_Z,
3428
    [INDEX_op_jz_subl] = CC_Z,
3429

    
3430
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3431
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3432
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3433

    
3434
    [INDEX_op_js_subb] = CC_S,
3435
    [INDEX_op_js_subw] = CC_S,
3436
    [INDEX_op_js_subl] = CC_S,
3437

    
3438
    [INDEX_op_jl_subb] = CC_O | CC_S,
3439
    [INDEX_op_jl_subw] = CC_O | CC_S,
3440
    [INDEX_op_jl_subl] = CC_O | CC_S,
3441

    
3442
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3443
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3444
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3445

    
3446
    [INDEX_op_loopnzw] = CC_Z,
3447
    [INDEX_op_loopnzl] = CC_Z,
3448
    [INDEX_op_loopzw] = CC_Z,
3449
    [INDEX_op_loopzl] = CC_Z,
3450

    
3451
    [INDEX_op_seto_T0_cc] = CC_O,
3452
    [INDEX_op_setb_T0_cc] = CC_C,
3453
    [INDEX_op_setz_T0_cc] = CC_Z,
3454
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3455
    [INDEX_op_sets_T0_cc] = CC_S,
3456
    [INDEX_op_setp_T0_cc] = CC_P,
3457
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3458
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3459

    
3460
    [INDEX_op_setb_T0_subb] = CC_C,
3461
    [INDEX_op_setb_T0_subw] = CC_C,
3462
    [INDEX_op_setb_T0_subl] = CC_C,
3463

    
3464
    [INDEX_op_setz_T0_subb] = CC_Z,
3465
    [INDEX_op_setz_T0_subw] = CC_Z,
3466
    [INDEX_op_setz_T0_subl] = CC_Z,
3467

    
3468
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3469
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3470
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3471

    
3472
    [INDEX_op_sets_T0_subb] = CC_S,
3473
    [INDEX_op_sets_T0_subw] = CC_S,
3474
    [INDEX_op_sets_T0_subl] = CC_S,
3475

    
3476
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3477
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3478
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3479

    
3480
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3481
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3482
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3483

    
3484
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3485
    [INDEX_op_cmc] = CC_C,
3486
    [INDEX_op_salc] = CC_C,
3487

    
3488
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3489
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3490
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3491
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3492
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3493
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3494
};
3495

    
3496
/* flags written by an operation */
3497
static uint16_t opc_write_flags[NB_OPS] = { 
3498
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3499
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3500
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3501
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3502
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3503
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3504
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3505
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3506
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3507
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3508
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3509
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3510
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3511
    /* subtle: due to the incl/decl implementation, C is used */
3512
    [INDEX_op_incl_T0_cc] = CC_OSZAPC, 
3513
    [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3514
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3515

    
3516
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3517
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3518
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3519
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3520
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3521
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3522
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3523
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3524
    
3525
    /* bcd */
3526
    [INDEX_op_aam] = CC_OSZAPC,
3527
    [INDEX_op_aad] = CC_OSZAPC,
3528
    [INDEX_op_aas] = CC_OSZAPC,
3529
    [INDEX_op_aaa] = CC_OSZAPC,
3530
    [INDEX_op_das] = CC_OSZAPC,
3531
    [INDEX_op_daa] = CC_OSZAPC,
3532

    
3533
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3534
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3535
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3536
    [INDEX_op_clc] = CC_C,
3537
    [INDEX_op_stc] = CC_C,
3538
    [INDEX_op_cmc] = CC_C,
3539

    
3540
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3541
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3542
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3543
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3544
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3545
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3546

    
3547
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3548
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3549
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3550
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3551
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3552
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3553

    
3554
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3555
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3556
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3557

    
3558
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3559
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3560
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3561

    
3562
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3563
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3564
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3565

    
3566
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3567
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3568
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3569
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3570

    
3571
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3572
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3573
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3574
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3575

    
3576
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3577
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3578
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3579
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3580
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3581
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3582
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3583
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3584

    
3585
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3586
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3587
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3588
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3589

    
3590
#undef STRINGOP
3591
#define STRINGOP(x) \
3592
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3593
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3594
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3595
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3596
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3597
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3598
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3599
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3600
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3601

    
3602
    STRINGOP(scas)
3603
    STRINGOP(repz_scas)
3604
    STRINGOP(repnz_scas)
3605
    STRINGOP(cmps)
3606
    STRINGOP(repz_cmps)
3607
    STRINGOP(repnz_cmps)
3608

    
3609
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3610
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3611
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3612

    
3613
    [INDEX_op_cmpxchg8b] = CC_Z,
3614
    [INDEX_op_lar] = CC_Z,
3615
    [INDEX_op_lsl] = CC_Z,
3616
};
3617

    
3618
/* simpler form of an operation if no flags need to be generated */
3619
static uint16_t opc_simpler[NB_OPS] = { 
3620
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3621
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3622
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3623
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3624
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3625
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3626
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3627
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3628

    
3629
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3630
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3631
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3632

    
3633
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3634
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3635
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3636

    
3637
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3638
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3639
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3640

    
3641
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3642
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3643
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3644

    
3645
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3646
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3647
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3648
};
3649

    
3650
static void optimize_flags_init(void)
3651
{
3652
    int i;
3653
    /* put default values in arrays */
3654
    for(i = 0; i < NB_OPS; i++) {
3655
        if (opc_simpler[i] == 0)
3656
            opc_simpler[i] = i;
3657
    }
3658
}
3659

    
3660
/* CPU flags computation optimization: we move backward thru the
3661
   generated code to see which flags are needed. The operation is
3662
   modified if suitable */
3663
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3664
{
3665
    uint16_t *opc_ptr;
3666
    int live_flags, write_flags, op;
3667

    
3668
    opc_ptr = opc_buf + opc_buf_len;
3669
    /* live_flags contains the flags needed by the next instructions
3670
       in the code. At the end of the bloc, we consider that all the
3671
       flags are live. */
3672
    live_flags = CC_OSZAPC;
3673
    while (opc_ptr > opc_buf) {
3674
        op = *--opc_ptr;
3675
        /* if none of the flags written by the instruction is used,
3676
           then we can try to find a simpler instruction */
3677
        write_flags = opc_write_flags[op];
3678
        if ((live_flags & write_flags) == 0) {
3679
            *opc_ptr = opc_simpler[op];
3680
        }
3681
        /* compute the live flags before the instruction */
3682
        live_flags &= ~write_flags;
3683
        live_flags |= opc_read_flags[op];
3684
    }
3685
}
3686

    
3687

    
3688
#ifdef DEBUG_DISAS
3689
static const char *op_str[] = {
3690
#define DEF(s, n, copy_size) #s,
3691
#include "opc-i386.h"
3692
#undef DEF
3693
};
3694

    
3695
static uint8_t op_nb_args[] = {
3696
#define DEF(s, n, copy_size) n,
3697
#include "opc-i386.h"
3698
#undef DEF
3699
};
3700

    
3701
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3702
{
3703
    const uint16_t *opc_ptr;
3704
    const uint32_t *opparam_ptr;
3705
    int c, n, i;
3706

    
3707
    opc_ptr = opc_buf;
3708
    opparam_ptr = opparam_buf;
3709
    for(;;) {
3710
        c = *opc_ptr++;
3711
        n = op_nb_args[c];
3712
        fprintf(logfile, "0x%04x: %s", 
3713
                (int)(opc_ptr - opc_buf - 1), op_str[c]);
3714
        for(i = 0; i < n; i++) {
3715
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
3716
        }
3717
        fprintf(logfile, "\n");
3718
        if (c == INDEX_op_end)
3719
            break;
3720
        opparam_ptr += n;
3721
    }
3722
}
3723

    
3724
#endif
3725

    
3726
/* XXX: make safe guess about sizes */
3727
#define MAX_OP_PER_INSTR 32
3728
#define OPC_BUF_SIZE 512
3729
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3730

    
3731
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3732

    
3733
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3734
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3735
static uint32_t gen_opc_pc[OPC_BUF_SIZE];
3736
static uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
3737

    
3738
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3739
   basic block 'tb'. If search_pc is TRUE, also generate PC
3740
   information for each intermediate instruction. */
3741
static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc)
3742
{
3743
    DisasContext dc1, *dc = &dc1;
3744
    uint8_t *pc_ptr;
3745
    uint16_t *gen_opc_end;
3746
    int flags, j, lj;
3747
    long ret;
3748
    uint8_t *pc_start;
3749
    uint8_t *cs_base;
3750
    
3751
    /* generate intermediate code */
3752
    pc_start = (uint8_t *)tb->pc;
3753
    cs_base = (uint8_t *)tb->cs_base;
3754
    flags = tb->flags;
3755
       
3756
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3757
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3758
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3759
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3760
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3761
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3762
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3763
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3764
    dc->cc_op = CC_OP_DYNAMIC;
3765
    dc->cs_base = cs_base;
3766
    dc->tb = tb;
3767

    
3768
    gen_opc_ptr = gen_opc_buf;
3769
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3770
    gen_opparam_ptr = gen_opparam_buf;
3771

    
3772
    dc->is_jmp = 0;
3773
    pc_ptr = pc_start;
3774
    lj = -1;
3775
    do {
3776
        if (search_pc) {
3777
            j = gen_opc_ptr - gen_opc_buf;
3778
            if (lj < j) {
3779
                lj++;
3780
                while (lj < j)
3781
                    gen_opc_instr_start[lj++] = 0;
3782
                gen_opc_pc[lj] = (uint32_t)pc_ptr;
3783
                gen_opc_instr_start[lj] = 1;
3784
            }
3785
        }
3786
        ret = disas_insn(dc, pc_ptr);
3787
        if (ret == -1) {
3788
            /* we trigger an illegal instruction operation only if it
3789
               is the first instruction. Otherwise, we simply stop
3790
               generating the code just before it */
3791
            if (pc_ptr == pc_start)
3792
                return -1;
3793
            else
3794
                break;
3795
        }
3796
        pc_ptr = (void *)ret;
3797
        /* if single step mode, we generate only one instruction and
3798
           generate an exception */
3799
        if (dc->tf)
3800
            break;
3801
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
3802
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3803
    /* we must store the eflags state if it is not already done */
3804
    if (dc->is_jmp != 3) {
3805
        if (dc->cc_op != CC_OP_DYNAMIC)
3806
            gen_op_set_cc_op(dc->cc_op);
3807
        if (dc->is_jmp != 1) {
3808
            /* we add an additionnal jmp to update the simulated PC */
3809
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3810
        }
3811
    }
3812
    if (dc->tf) {
3813
        gen_op_raise_exception(EXCP01_SSTP);
3814
    }
3815
    if (dc->is_jmp != 3) {
3816
        /* indicate that the hash table must be used to find the next TB */
3817
        gen_op_movl_T0_0();
3818
    }
3819

    
3820
    *gen_opc_ptr = INDEX_op_end;
3821

    
3822
#ifdef DEBUG_DISAS
3823
    if (loglevel) {
3824
        fprintf(logfile, "----------------\n");
3825
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3826
        disas(logfile, pc_start, pc_ptr - pc_start,
3827
              dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3828
        fprintf(logfile, "\n");
3829

    
3830
        fprintf(logfile, "OP:\n");
3831
        dump_ops(gen_opc_buf, gen_opparam_buf);
3832
        fprintf(logfile, "\n");
3833
    }
3834
#endif
3835

    
3836
    /* optimize flag computations */
3837
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3838

    
3839
#ifdef DEBUG_DISAS
3840
    if (loglevel) {
3841
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3842
        dump_ops(gen_opc_buf, gen_opparam_buf);
3843
        fprintf(logfile, "\n");
3844
    }
3845
#endif
3846
    if (!search_pc)
3847
        tb->size = pc_ptr - pc_start;
3848
    return 0;
3849
}
3850

    
3851

    
3852
/* return non zero if the very first instruction is invalid so that
3853
   the virtual CPU can trigger an exception. 
3854

3855
   '*gen_code_size_ptr' contains the size of the generated code (host
3856
   code).
3857
*/
3858
int cpu_x86_gen_code(TranslationBlock *tb,
3859
                     int max_code_size, int *gen_code_size_ptr)
3860
{
3861
    uint8_t *gen_code_buf;
3862
    int gen_code_size;
3863

    
3864
    if (gen_intermediate_code(tb, 0) < 0)
3865
        return -1;
3866

    
3867
    /* generate machine code */
3868
    tb->tb_next_offset[0] = 0xffff;
3869
    tb->tb_next_offset[1] = 0xffff;
3870
    gen_code_buf = tb->tc_ptr;
3871
    gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3872
#ifdef USE_DIRECT_JUMP
3873
                                tb->tb_jmp_offset,
3874
#else
3875
                                NULL,
3876
#endif
3877
                                gen_opc_buf, gen_opparam_buf);
3878
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3879
    
3880
    *gen_code_size_ptr = gen_code_size;
3881
#ifdef DEBUG_DISAS
3882
    if (loglevel) {
3883
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3884
        disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3885
        fprintf(logfile, "\n");
3886
        fflush(logfile);
3887
    }
3888
#endif
3889
    return 0;
3890
}
3891

    
3892
static const unsigned short opc_copy_size[] = {
3893
#define DEF(s, n, copy_size) copy_size,
3894
#include "opc-i386.h"
3895
#undef DEF
3896
};
3897

    
3898
/* The simulated PC corresponding to
3899
   'searched_pc' in the generated code is searched. 0 is returned if
3900
   found. *found_pc contains the found PC. 
3901
 */
3902
int cpu_x86_search_pc(TranslationBlock *tb, 
3903
                      uint32_t *found_pc, unsigned long searched_pc)
3904
{
3905
    int j, c;
3906
    unsigned long tc_ptr;
3907
    uint16_t *opc_ptr;
3908

    
3909
    if (gen_intermediate_code(tb, 1) < 0)
3910
        return -1;
3911
    
3912
    /* find opc index corresponding to search_pc */
3913
    tc_ptr = (unsigned long)tb->tc_ptr;
3914
    if (searched_pc < tc_ptr)
3915
        return -1;
3916
    j = 0;
3917
    opc_ptr = gen_opc_buf;
3918
    for(;;) {
3919
        c = *opc_ptr;
3920
        if (c == INDEX_op_end)
3921
            return -1;
3922
        tc_ptr += opc_copy_size[c];
3923
        if (searched_pc < tc_ptr)
3924
            break;
3925
        opc_ptr++;
3926
    }
3927
    j = opc_ptr - gen_opc_buf;
3928
    /* now find start of instruction before */
3929
    while (gen_opc_instr_start[j] == 0)
3930
        j--;
3931
    *found_pc = gen_opc_pc[j];
3932
    return 0;
3933
}
3934

    
3935

    
3936
CPUX86State *cpu_x86_init(void)
3937
{
3938
    CPUX86State *env;
3939
    int i;
3940
    static int inited;
3941

    
3942
    cpu_x86_tblocks_init();
3943

    
3944
    env = malloc(sizeof(CPUX86State));
3945
    if (!env)
3946
        return NULL;
3947
    memset(env, 0, sizeof(CPUX86State));
3948
    /* basic FPU init */
3949
    for(i = 0;i < 8; i++)
3950
        env->fptags[i] = 1;
3951
    env->fpuc = 0x37f;
3952
    /* flags setup : we activate the IRQs by default as in user mode */
3953
    env->eflags = 0x2 | IF_MASK;
3954

    
3955
    /* init various static tables */
3956
    if (!inited) {
3957
        inited = 1;
3958
        optimize_flags_init();
3959
        page_init();
3960
    }
3961
    return env;
3962
}
3963

    
3964
void cpu_x86_close(CPUX86State *env)
3965
{
3966
    free(env);
3967
}
3968

    
3969
static const char *cc_op_str[] = {
3970
    "DYNAMIC",
3971
    "EFLAGS",
3972
    "MUL",
3973
    "ADDB",
3974
    "ADDW",
3975
    "ADDL",
3976
    "ADCB",
3977
    "ADCW",
3978
    "ADCL",
3979
    "SUBB",
3980
    "SUBW",
3981
    "SUBL",
3982
    "SBBB",
3983
    "SBBW",
3984
    "SBBL",
3985
    "LOGICB",
3986
    "LOGICW",
3987
    "LOGICL",
3988
    "INCB",
3989
    "INCW",
3990
    "INCL",
3991
    "DECB",
3992
    "DECW",
3993
    "DECL",
3994
    "SHLB",
3995
    "SHLW",
3996
    "SHLL",
3997
    "SARB",
3998
    "SARW",
3999
    "SARL",
4000
};
4001

    
4002
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4003
{
4004
    int eflags;
4005
    char cc_op_name[32];
4006

    
4007
    eflags = env->eflags;
4008
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4009
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4010
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4011
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
4012
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
4013
            env->eip, eflags,
4014
            eflags & DF_MASK ? 'D' : '-',
4015
            eflags & CC_O ? 'O' : '-',
4016
            eflags & CC_S ? 'S' : '-',
4017
            eflags & CC_Z ? 'Z' : '-',
4018
            eflags & CC_A ? 'A' : '-',
4019
            eflags & CC_P ? 'P' : '-',
4020
            eflags & CC_C ? 'C' : '-');
4021
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4022
            env->segs[R_CS],
4023
            env->segs[R_SS],
4024
            env->segs[R_DS],
4025
            env->segs[R_ES],
4026
            env->segs[R_FS],
4027
            env->segs[R_GS]);
4028
    if (flags & X86_DUMP_CCOP) {
4029
        if ((unsigned)env->cc_op < CC_OP_NB)
4030
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
4031
        else
4032
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4033
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4034
                env->cc_src, env->cc_dst, cc_op_name);
4035
    }
4036
    if (flags & X86_DUMP_FPU) {
4037
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
4038
                (double)env->fpregs[0], 
4039
                (double)env->fpregs[1], 
4040
                (double)env->fpregs[2], 
4041
                (double)env->fpregs[3]);
4042
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
4043
                (double)env->fpregs[4], 
4044
                (double)env->fpregs[5], 
4045
                (double)env->fpregs[7], 
4046
                (double)env->fpregs[8]);
4047
    }
4048
}