Statistics
| Branch: | Revision:

root / translate-i386.c @ ae48a073

History | View | Annotate | Download (101.7 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
#define DEBUG_DISAS
29

    
30
#define IN_OP_I386
31
#include "cpu-i386.h"
32

    
33
/* dump all code */
34
#ifdef DEBUG_DISAS
35
#include "dis-asm.h"
36
#endif
37

    
38
#ifndef offsetof
39
#define offsetof(type, field) ((size_t) &((type *)0)->field)
40
#endif
41

    
42
/* XXX: move that elsewhere */
43
static uint16_t *gen_opc_ptr;
44
static uint32_t *gen_opparam_ptr;
45
int __op_param1, __op_param2, __op_param3;
46

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

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

    
59
#ifdef __powerpc__
60

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

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

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

    
82
extern FILE *logfile;
83
extern int loglevel;
84

    
85
#define PREFIX_REPZ   0x01
86
#define PREFIX_REPNZ  0x02
87
#define PREFIX_LOCK   0x04
88
#define PREFIX_DATA   0x08
89
#define PREFIX_ADR    0x10
90
#define PREFIX_FWAIT  0x20
91

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

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

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

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

    
141
#include "op-i386.h"
142

    
143
/* operand size */
144
enum {
145
    OT_BYTE = 0,
146
    OT_WORD,
147
    OT_LONG, 
148
    OT_QUAD,
149
};
150

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

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

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

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

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

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

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

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

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

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

    
434
static const int cc_op_arithb[8] = {
435
    CC_OP_ADDB,
436
    CC_OP_LOGICB,
437
    CC_OP_ADDB,
438
    CC_OP_SUBB,
439
    CC_OP_LOGICB,
440
    CC_OP_SUBB,
441
    CC_OP_LOGICB,
442
    CC_OP_SUBB,
443
};
444

    
445
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
446
    gen_op_cmpxchgb_T0_T1_EAX_cc,
447
    gen_op_cmpxchgw_T0_T1_EAX_cc,
448
    gen_op_cmpxchgl_T0_T1_EAX_cc,
449
};
450

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

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

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

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

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

    
532
static GenOpFunc *gen_op_lds_T0_A0[3] = {
533
    gen_op_ldsb_T0_A0,
534
    gen_op_ldsw_T0_A0,
535
};
536

    
537
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
538
    gen_op_ldub_T0_A0,
539
    gen_op_lduw_T0_A0,
540
};
541

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

    
549
static GenOpFunc *gen_op_ld_T1_A0[3] = {
550
    gen_op_ldub_T1_A0,
551
    gen_op_lduw_T1_A0,
552
    gen_op_ldl_T1_A0,
553
};
554

    
555
static GenOpFunc *gen_op_st_T0_A0[3] = {
556
    gen_op_stb_T0_A0,
557
    gen_op_stw_T0_A0,
558
    gen_op_stl_T0_A0,
559
};
560

    
561
/* the _a32 and _a16 string operations use A0 as the base register. */
562

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

    
579
static GenOpFunc *gen_op_stos[9 * 2] = {
580
    STRINGOP(stos)
581
    STRINGOP(rep_stos)
582
};
583

    
584
static GenOpFunc *gen_op_lods[9 * 2] = {
585
    STRINGOP(lods)
586
    STRINGOP(rep_lods)
587
};
588

    
589
static GenOpFunc *gen_op_scas[9 * 3] = {
590
    STRINGOP(scas)
591
    STRINGOP(repz_scas)
592
    STRINGOP(repnz_scas)
593
};
594

    
595
static GenOpFunc *gen_op_cmps[9 * 3] = {
596
    STRINGOP(cmps)
597
    STRINGOP(repz_cmps)
598
    STRINGOP(repnz_cmps)
599
};
600

    
601
static GenOpFunc *gen_op_ins[9 * 2] = {
602
    STRINGOP(ins)
603
    STRINGOP(rep_ins)
604
};
605

    
606

    
607
static GenOpFunc *gen_op_outs[9 * 2] = {
608
    STRINGOP(outs)
609
    STRINGOP(rep_outs)
610
};
611

    
612

    
613
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
614
{
615
    int index, override;
616

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

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

    
654

    
655
static GenOpFunc *gen_op_in[3] = {
656
    gen_op_inb_T0_T1,
657
    gen_op_inw_T0_T1,
658
    gen_op_inl_T0_T1,
659
};
660

    
661
static GenOpFunc *gen_op_out[3] = {
662
    gen_op_outb_T0_T1,
663
    gen_op_outw_T0_T1,
664
    gen_op_outl_T0_T1,
665
};
666

    
667
enum {
668
    JCC_O,
669
    JCC_B,
670
    JCC_Z,
671
    JCC_BE,
672
    JCC_S,
673
    JCC_P,
674
    JCC_L,
675
    JCC_LE,
676
};
677

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

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

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

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

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

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

    
822
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
823
{
824
    gen_op_movl_T1_im(c);
825
    gen_op(s1, op, ot, d, OR_TMP1);
826
}
827

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

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

    
855
    gen_op_shift_T0_T1_cc[ot][op]();
856

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

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

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

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

    
885
    if (s->aflag) {
886

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

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

    
1007
    opreg = OR_A0;
1008
    disp = 0;
1009
    *reg_ptr = opreg;
1010
    *offset_ptr = disp;
1011
}
1012

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

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

    
1045
static inline uint32_t insn_get(DisasContext *s, int ot)
1046
{
1047
    uint32_t ret;
1048

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

    
1067
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1068
{
1069
    int inv, jcc_op;
1070
    GenOpFunc2 *func;
1071

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

    
1134
static void gen_setcc(DisasContext *s, int b)
1135
{
1136
    int inv, jcc_op;
1137
    GenOpFunc *func;
1138

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

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

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

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

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

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

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

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

    
1308
    ot = s->dflag + OT_WORD;
1309
    level &= 0x1f;
1310
    level1 = level;
1311
    opsize = 2 << s->dflag;
1312

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

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

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

    
1400
    if (prefixes & PREFIX_DATA)
1401
        dflag ^= 1;
1402
    if (prefixes & PREFIX_ADR)
1403
        aflag ^= 1;
1404

    
1405
    s->prefix = prefixes;
1406
    s->aflag = aflag;
1407
    s->dflag = dflag;
1408

    
1409
    /* lock generation */
1410
    if (prefixes & PREFIX_LOCK)
1411
        gen_op_lock();
1412

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

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

    
1482
    case 0x80: /* GRP1 */
1483
    case 0x81:
1484
    case 0x83:
1485
        {
1486
            int val;
1487

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3276
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3277
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3278

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

    
3286
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3287
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3288
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3289
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3290
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3291
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3292

    
3293
    [INDEX_op_into] = CC_O,
3294

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

    
3304
    [INDEX_op_jb_subb] = CC_C,
3305
    [INDEX_op_jb_subw] = CC_C,
3306
    [INDEX_op_jb_subl] = CC_C,
3307

    
3308
    [INDEX_op_jz_subb] = CC_Z,
3309
    [INDEX_op_jz_subw] = CC_Z,
3310
    [INDEX_op_jz_subl] = CC_Z,
3311

    
3312
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3313
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3314
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3315

    
3316
    [INDEX_op_js_subb] = CC_S,
3317
    [INDEX_op_js_subw] = CC_S,
3318
    [INDEX_op_js_subl] = CC_S,
3319

    
3320
    [INDEX_op_jl_subb] = CC_O | CC_S,
3321
    [INDEX_op_jl_subw] = CC_O | CC_S,
3322
    [INDEX_op_jl_subl] = CC_O | CC_S,
3323

    
3324
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3325
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3326
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3327

    
3328
    [INDEX_op_loopnzw] = CC_Z,
3329
    [INDEX_op_loopnzl] = CC_Z,
3330
    [INDEX_op_loopzw] = CC_Z,
3331
    [INDEX_op_loopzl] = CC_Z,
3332

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

    
3342
    [INDEX_op_setb_T0_subb] = CC_C,
3343
    [INDEX_op_setb_T0_subw] = CC_C,
3344
    [INDEX_op_setb_T0_subl] = CC_C,
3345

    
3346
    [INDEX_op_setz_T0_subb] = CC_Z,
3347
    [INDEX_op_setz_T0_subw] = CC_Z,
3348
    [INDEX_op_setz_T0_subl] = CC_Z,
3349

    
3350
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3351
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3352
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3353

    
3354
    [INDEX_op_sets_T0_subb] = CC_S,
3355
    [INDEX_op_sets_T0_subw] = CC_S,
3356
    [INDEX_op_sets_T0_subl] = CC_S,
3357

    
3358
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3359
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3360
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3361

    
3362
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3363
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3364
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3365

    
3366
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3367
    [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
3368
    [INDEX_op_cmc] = CC_C,
3369
    [INDEX_op_salc] = CC_C,
3370

    
3371
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3372
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3373
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3374
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3375
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3376
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3377
};
3378

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

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

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

    
3424
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3425
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3426
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3427
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3428
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3429
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3430

    
3431
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3432
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3433
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3434
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3435
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3436
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3437

    
3438
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3439
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3440
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3441

    
3442
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3443
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3444
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3445

    
3446
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3447
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3448
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3449

    
3450
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3451
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3452
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3453
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3454

    
3455
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3456
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3457
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3458
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3459

    
3460
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3461
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3462
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3463
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3464
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3465
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3466
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3467
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3468

    
3469
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3470
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3471
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3472
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3473

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

    
3486
    STRINGOP(scas)
3487
    STRINGOP(repz_scas)
3488
    STRINGOP(repnz_scas)
3489
    STRINGOP(cmps)
3490
    STRINGOP(repz_cmps)
3491
    STRINGOP(repnz_cmps)
3492

    
3493
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3494
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3495
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3496

    
3497
    [INDEX_op_cmpxchg8b] = CC_Z,
3498
};
3499

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

    
3511
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3512
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3513
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3514

    
3515
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3516
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3517
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3518

    
3519
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3520
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3521
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3522

    
3523
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3524
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3525
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3526

    
3527
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3528
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3529
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3530
};
3531

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

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

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

    
3569

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

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

    
3583
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3584
{
3585
    const uint16_t *opc_ptr;
3586
    const uint32_t *opparam_ptr;
3587
    int c, n, i;
3588

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

    
3605
#endif
3606

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

    
3613
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3614

    
3615
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3616
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3617

    
3618
/* return non zero if the very first instruction is invalid so that
3619
   the virtual CPU can trigger an exception. */
3620
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3621
                     int *gen_code_size_ptr,
3622
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3623
{
3624
    DisasContext dc1, *dc = &dc1;
3625
    uint8_t *pc_ptr;
3626
    uint16_t *gen_opc_end;
3627
    int gen_code_size;
3628
    long ret;
3629
#ifdef DEBUG_DISAS
3630
    struct disassemble_info disasm_info;
3631
#endif
3632
    
3633
    /* generate intermediate code */
3634

    
3635
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3636
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3637
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3638
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3639
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3640
    dc->cc_op = CC_OP_DYNAMIC;
3641
    dc->cs_base = cs_base;
3642

    
3643
    gen_opc_ptr = gen_opc_buf;
3644
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3645
    gen_opparam_ptr = gen_opparam_buf;
3646

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

    
3671
    /* optimize flag computations */
3672
#ifdef DEBUG_DISAS
3673
    if (loglevel) {
3674
        uint8_t *pc;
3675
        int count;
3676

    
3677
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3678
#if 0        
3679
        disasm_info.flavour = bfd_get_flavour (abfd);
3680
        disasm_info.arch = bfd_get_arch (abfd);
3681
        disasm_info.mach = bfd_get_mach (abfd);
3682
#endif
3683
        disasm_info.endian = BFD_ENDIAN_LITTLE;
3684
        if (dc->code32)
3685
            disasm_info.mach = bfd_mach_i386_i386;
3686
        else
3687
            disasm_info.mach = bfd_mach_i386_i8086;
3688
        fprintf(logfile, "----------------\n");
3689
        fprintf(logfile, "IN:\n");
3690
        disasm_info.buffer = pc_start;
3691
        disasm_info.buffer_vma = (unsigned long)pc_start;
3692
        disasm_info.buffer_length = pc_ptr - pc_start;
3693
        pc = pc_start;
3694
        while (pc < pc_ptr) {
3695
            fprintf(logfile, "0x%08lx:  ", (long)pc);
3696
            count = print_insn_i386((unsigned long)pc, &disasm_info);
3697
            fprintf(logfile, "\n");
3698
            pc += count;
3699
        }
3700
        fprintf(logfile, "\n");
3701
        
3702
        fprintf(logfile, "OP:\n");
3703
        dump_ops(gen_opc_buf, gen_opparam_buf);
3704
        fprintf(logfile, "\n");
3705
    }
3706
#endif
3707

    
3708
    /* optimize flag computations */
3709
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3710

    
3711
#ifdef DEBUG_DISAS
3712
    if (loglevel) {
3713
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3714
        dump_ops(gen_opc_buf, gen_opparam_buf);
3715
        fprintf(logfile, "\n");
3716
    }
3717
#endif
3718

    
3719
    /* generate machine code */
3720
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3721
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3722
    *gen_code_size_ptr = gen_code_size;
3723

    
3724
#ifdef DEBUG_DISAS
3725
    if (loglevel) {
3726
        uint8_t *pc;
3727
        int count;
3728

    
3729
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3730
#if 0        
3731
        disasm_info.flavour = bfd_get_flavour (abfd);
3732
        disasm_info.arch = bfd_get_arch (abfd);
3733
        disasm_info.mach = bfd_get_mach (abfd);
3734
#endif
3735
#ifdef WORDS_BIGENDIAN
3736
        disasm_info.endian = BFD_ENDIAN_BIG;
3737
#else
3738
        disasm_info.endian = BFD_ENDIAN_LITTLE;
3739
#endif        
3740
        disasm_info.mach = bfd_mach_i386_i386;
3741

    
3742
        pc = gen_code_buf;
3743
        disasm_info.buffer = pc;
3744
        disasm_info.buffer_vma = (unsigned long)pc;
3745
        disasm_info.buffer_length = *gen_code_size_ptr;
3746
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3747
        while (pc < gen_code_buf + *gen_code_size_ptr) {
3748
            fprintf(logfile, "0x%08lx:  ", (long)pc);
3749
            count = print_insn_i386((unsigned long)pc, &disasm_info);
3750
            fprintf(logfile, "\n");
3751
            pc += count;
3752
        }
3753
        fprintf(logfile, "\n");
3754
        fflush(logfile);
3755
    }
3756
#endif
3757
    return 0;
3758
}
3759

    
3760
CPUX86State *cpu_x86_init(void)
3761
{
3762
    CPUX86State *env;
3763
    int i;
3764
    static int inited;
3765

    
3766
    cpu_x86_tblocks_init();
3767

    
3768
    env = malloc(sizeof(CPUX86State));
3769
    if (!env)
3770
        return NULL;
3771
    memset(env, 0, sizeof(CPUX86State));
3772
    /* basic FPU init */
3773
    for(i = 0;i < 8; i++)
3774
        env->fptags[i] = 1;
3775
    env->fpuc = 0x37f;
3776
    /* flags setup : we activate the IRQs by default as in user mode */
3777
    env->eflags = 0x2 | IF_MASK;
3778

    
3779
    /* init various static tables */
3780
    if (!inited) {
3781
        inited = 1;
3782
        optimize_flags_init();
3783
    }
3784
    return env;
3785
}
3786

    
3787
void cpu_x86_close(CPUX86State *env)
3788
{
3789
    free(env);
3790
}