Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 9772c73b

History | View | Annotate | Download (134 kB)

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

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "disas.h"
31

    
32
/* XXX: move that elsewhere */
33
static uint16_t *gen_opc_ptr;
34
static uint32_t *gen_opparam_ptr;
35

    
36
#define PREFIX_REPZ   0x01
37
#define PREFIX_REPNZ  0x02
38
#define PREFIX_LOCK   0x04
39
#define PREFIX_DATA   0x08
40
#define PREFIX_ADR    0x10
41

    
42
typedef struct DisasContext {
43
    /* current insn context */
44
    int override; /* -1 if no override */
45
    int prefix;
46
    int aflag, dflag;
47
    uint8_t *pc; /* pc = eip + cs_base */
48
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
49
                   static state change (stop translation) */
50
    /* current block context */
51
    uint8_t *cs_base; /* base of CS segment */
52
    int pe;     /* protected mode */
53
    int code32; /* 32 bit code segment */
54
    int ss32;   /* 32 bit stack segment */
55
    int cc_op;  /* current CC operation */
56
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
57
    int f_st;   /* currently unused */
58
    int vm86;   /* vm86 mode */
59
    int cpl;
60
    int iopl;
61
    int tf;     /* TF cpu flag */
62
    int singlestep_enabled; /* "hardware" single step enabled */
63
    int jmp_opt; /* use direct block chaining for direct jumps */
64
    int mem_index; /* select memory access functions */
65
    int flags; /* all execution flags */
66
    struct TranslationBlock *tb;
67
    int popl_esp_hack; /* for correct popl with esp base handling */
68
} DisasContext;
69

    
70
static void gen_eob(DisasContext *s);
71
static void gen_jmp(DisasContext *s, unsigned int eip);
72

    
73
/* i386 arith/logic operations */
74
enum {
75
    OP_ADDL, 
76
    OP_ORL, 
77
    OP_ADCL, 
78
    OP_SBBL,
79
    OP_ANDL, 
80
    OP_SUBL, 
81
    OP_XORL, 
82
    OP_CMPL,
83
};
84

    
85
/* i386 shift ops */
86
enum {
87
    OP_ROL, 
88
    OP_ROR, 
89
    OP_RCL, 
90
    OP_RCR, 
91
    OP_SHL, 
92
    OP_SHR, 
93
    OP_SHL1, /* undocumented */
94
    OP_SAR = 7,
95
};
96

    
97
enum {
98
#define DEF(s, n, copy_size) INDEX_op_ ## s,
99
#include "opc.h"
100
#undef DEF
101
    NB_OPS,
102
};
103

    
104
#include "gen-op.h"
105

    
106
/* operand size */
107
enum {
108
    OT_BYTE = 0,
109
    OT_WORD,
110
    OT_LONG, 
111
    OT_QUAD,
112
};
113

    
114
enum {
115
    /* I386 int registers */
116
    OR_EAX,   /* MUST be even numbered */
117
    OR_ECX,
118
    OR_EDX,
119
    OR_EBX,
120
    OR_ESP,
121
    OR_EBP,
122
    OR_ESI,
123
    OR_EDI,
124
    OR_TMP0,    /* temporary operand register */
125
    OR_TMP1,
126
    OR_A0, /* temporary register used when doing address evaluation */
127
    OR_ZERO, /* fixed zero register */
128
    NB_OREGS,
129
};
130

    
131
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
132
    [OT_BYTE] = {
133
        gen_op_movb_EAX_T0,
134
        gen_op_movb_ECX_T0,
135
        gen_op_movb_EDX_T0,
136
        gen_op_movb_EBX_T0,
137
        gen_op_movh_EAX_T0,
138
        gen_op_movh_ECX_T0,
139
        gen_op_movh_EDX_T0,
140
        gen_op_movh_EBX_T0,
141
    },
142
    [OT_WORD] = {
143
        gen_op_movw_EAX_T0,
144
        gen_op_movw_ECX_T0,
145
        gen_op_movw_EDX_T0,
146
        gen_op_movw_EBX_T0,
147
        gen_op_movw_ESP_T0,
148
        gen_op_movw_EBP_T0,
149
        gen_op_movw_ESI_T0,
150
        gen_op_movw_EDI_T0,
151
    },
152
    [OT_LONG] = {
153
        gen_op_movl_EAX_T0,
154
        gen_op_movl_ECX_T0,
155
        gen_op_movl_EDX_T0,
156
        gen_op_movl_EBX_T0,
157
        gen_op_movl_ESP_T0,
158
        gen_op_movl_EBP_T0,
159
        gen_op_movl_ESI_T0,
160
        gen_op_movl_EDI_T0,
161
    },
162
};
163

    
164
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
165
    [OT_BYTE] = {
166
        gen_op_movb_EAX_T1,
167
        gen_op_movb_ECX_T1,
168
        gen_op_movb_EDX_T1,
169
        gen_op_movb_EBX_T1,
170
        gen_op_movh_EAX_T1,
171
        gen_op_movh_ECX_T1,
172
        gen_op_movh_EDX_T1,
173
        gen_op_movh_EBX_T1,
174
    },
175
    [OT_WORD] = {
176
        gen_op_movw_EAX_T1,
177
        gen_op_movw_ECX_T1,
178
        gen_op_movw_EDX_T1,
179
        gen_op_movw_EBX_T1,
180
        gen_op_movw_ESP_T1,
181
        gen_op_movw_EBP_T1,
182
        gen_op_movw_ESI_T1,
183
        gen_op_movw_EDI_T1,
184
    },
185
    [OT_LONG] = {
186
        gen_op_movl_EAX_T1,
187
        gen_op_movl_ECX_T1,
188
        gen_op_movl_EDX_T1,
189
        gen_op_movl_EBX_T1,
190
        gen_op_movl_ESP_T1,
191
        gen_op_movl_EBP_T1,
192
        gen_op_movl_ESI_T1,
193
        gen_op_movl_EDI_T1,
194
    },
195
};
196

    
197
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
198
    [0] = {
199
        gen_op_movw_EAX_A0,
200
        gen_op_movw_ECX_A0,
201
        gen_op_movw_EDX_A0,
202
        gen_op_movw_EBX_A0,
203
        gen_op_movw_ESP_A0,
204
        gen_op_movw_EBP_A0,
205
        gen_op_movw_ESI_A0,
206
        gen_op_movw_EDI_A0,
207
    },
208
    [1] = {
209
        gen_op_movl_EAX_A0,
210
        gen_op_movl_ECX_A0,
211
        gen_op_movl_EDX_A0,
212
        gen_op_movl_EBX_A0,
213
        gen_op_movl_ESP_A0,
214
        gen_op_movl_EBP_A0,
215
        gen_op_movl_ESI_A0,
216
        gen_op_movl_EDI_A0,
217
    },
218
};
219

    
220
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
221
{
222
    [OT_BYTE] = {
223
        {
224
            gen_op_movl_T0_EAX,
225
            gen_op_movl_T0_ECX,
226
            gen_op_movl_T0_EDX,
227
            gen_op_movl_T0_EBX,
228
            gen_op_movh_T0_EAX,
229
            gen_op_movh_T0_ECX,
230
            gen_op_movh_T0_EDX,
231
            gen_op_movh_T0_EBX,
232
        },
233
        {
234
            gen_op_movl_T1_EAX,
235
            gen_op_movl_T1_ECX,
236
            gen_op_movl_T1_EDX,
237
            gen_op_movl_T1_EBX,
238
            gen_op_movh_T1_EAX,
239
            gen_op_movh_T1_ECX,
240
            gen_op_movh_T1_EDX,
241
            gen_op_movh_T1_EBX,
242
        },
243
    },
244
    [OT_WORD] = {
245
        {
246
            gen_op_movl_T0_EAX,
247
            gen_op_movl_T0_ECX,
248
            gen_op_movl_T0_EDX,
249
            gen_op_movl_T0_EBX,
250
            gen_op_movl_T0_ESP,
251
            gen_op_movl_T0_EBP,
252
            gen_op_movl_T0_ESI,
253
            gen_op_movl_T0_EDI,
254
        },
255
        {
256
            gen_op_movl_T1_EAX,
257
            gen_op_movl_T1_ECX,
258
            gen_op_movl_T1_EDX,
259
            gen_op_movl_T1_EBX,
260
            gen_op_movl_T1_ESP,
261
            gen_op_movl_T1_EBP,
262
            gen_op_movl_T1_ESI,
263
            gen_op_movl_T1_EDI,
264
        },
265
    },
266
    [OT_LONG] = {
267
        {
268
            gen_op_movl_T0_EAX,
269
            gen_op_movl_T0_ECX,
270
            gen_op_movl_T0_EDX,
271
            gen_op_movl_T0_EBX,
272
            gen_op_movl_T0_ESP,
273
            gen_op_movl_T0_EBP,
274
            gen_op_movl_T0_ESI,
275
            gen_op_movl_T0_EDI,
276
        },
277
        {
278
            gen_op_movl_T1_EAX,
279
            gen_op_movl_T1_ECX,
280
            gen_op_movl_T1_EDX,
281
            gen_op_movl_T1_EBX,
282
            gen_op_movl_T1_ESP,
283
            gen_op_movl_T1_EBP,
284
            gen_op_movl_T1_ESI,
285
            gen_op_movl_T1_EDI,
286
        },
287
    },
288
};
289

    
290
static GenOpFunc *gen_op_movl_A0_reg[8] = {
291
    gen_op_movl_A0_EAX,
292
    gen_op_movl_A0_ECX,
293
    gen_op_movl_A0_EDX,
294
    gen_op_movl_A0_EBX,
295
    gen_op_movl_A0_ESP,
296
    gen_op_movl_A0_EBP,
297
    gen_op_movl_A0_ESI,
298
    gen_op_movl_A0_EDI,
299
};
300

    
301
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
302
    [0] = {
303
        gen_op_addl_A0_EAX,
304
        gen_op_addl_A0_ECX,
305
        gen_op_addl_A0_EDX,
306
        gen_op_addl_A0_EBX,
307
        gen_op_addl_A0_ESP,
308
        gen_op_addl_A0_EBP,
309
        gen_op_addl_A0_ESI,
310
        gen_op_addl_A0_EDI,
311
    },
312
    [1] = {
313
        gen_op_addl_A0_EAX_s1,
314
        gen_op_addl_A0_ECX_s1,
315
        gen_op_addl_A0_EDX_s1,
316
        gen_op_addl_A0_EBX_s1,
317
        gen_op_addl_A0_ESP_s1,
318
        gen_op_addl_A0_EBP_s1,
319
        gen_op_addl_A0_ESI_s1,
320
        gen_op_addl_A0_EDI_s1,
321
    },
322
    [2] = {
323
        gen_op_addl_A0_EAX_s2,
324
        gen_op_addl_A0_ECX_s2,
325
        gen_op_addl_A0_EDX_s2,
326
        gen_op_addl_A0_EBX_s2,
327
        gen_op_addl_A0_ESP_s2,
328
        gen_op_addl_A0_EBP_s2,
329
        gen_op_addl_A0_ESI_s2,
330
        gen_op_addl_A0_EDI_s2,
331
    },
332
    [3] = {
333
        gen_op_addl_A0_EAX_s3,
334
        gen_op_addl_A0_ECX_s3,
335
        gen_op_addl_A0_EDX_s3,
336
        gen_op_addl_A0_EBX_s3,
337
        gen_op_addl_A0_ESP_s3,
338
        gen_op_addl_A0_EBP_s3,
339
        gen_op_addl_A0_ESI_s3,
340
        gen_op_addl_A0_EDI_s3,
341
    },
342
};
343

    
344
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
345
    [0] = {
346
        gen_op_cmovw_EAX_T1_T0,
347
        gen_op_cmovw_ECX_T1_T0,
348
        gen_op_cmovw_EDX_T1_T0,
349
        gen_op_cmovw_EBX_T1_T0,
350
        gen_op_cmovw_ESP_T1_T0,
351
        gen_op_cmovw_EBP_T1_T0,
352
        gen_op_cmovw_ESI_T1_T0,
353
        gen_op_cmovw_EDI_T1_T0,
354
    },
355
    [1] = {
356
        gen_op_cmovl_EAX_T1_T0,
357
        gen_op_cmovl_ECX_T1_T0,
358
        gen_op_cmovl_EDX_T1_T0,
359
        gen_op_cmovl_EBX_T1_T0,
360
        gen_op_cmovl_ESP_T1_T0,
361
        gen_op_cmovl_EBP_T1_T0,
362
        gen_op_cmovl_ESI_T1_T0,
363
        gen_op_cmovl_EDI_T1_T0,
364
    },
365
};
366

    
367
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
368
    NULL,
369
    gen_op_orl_T0_T1,
370
    NULL,
371
    NULL,
372
    gen_op_andl_T0_T1,
373
    NULL,
374
    gen_op_xorl_T0_T1,
375
    NULL,
376
};
377

    
378
#define DEF_ARITHC(SUFFIX)\
379
    {\
380
        gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
381
        gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
382
    },\
383
    {\
384
        gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
385
        gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
386
    },\
387
    {\
388
        gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
389
        gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
390
    },
391

    
392
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
393
    DEF_ARITHC( )
394
};
395

    
396
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[9][2] = {
397
    DEF_ARITHC(_raw)
398
#ifndef CONFIG_USER_ONLY
399
    DEF_ARITHC(_kernel)
400
    DEF_ARITHC(_user)
401
#endif
402
};
403

    
404
static const int cc_op_arithb[8] = {
405
    CC_OP_ADDB,
406
    CC_OP_LOGICB,
407
    CC_OP_ADDB,
408
    CC_OP_SUBB,
409
    CC_OP_LOGICB,
410
    CC_OP_SUBB,
411
    CC_OP_LOGICB,
412
    CC_OP_SUBB,
413
};
414

    
415
#define DEF_CMPXCHG(SUFFIX)\
416
    gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
417
    gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
418
    gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,
419

    
420

    
421
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
422
    DEF_CMPXCHG( )
423
};
424

    
425
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[9] = {
426
    DEF_CMPXCHG(_raw)
427
#ifndef CONFIG_USER_ONLY
428
    DEF_CMPXCHG(_kernel)
429
    DEF_CMPXCHG(_user)
430
#endif
431
};
432

    
433
#define DEF_SHIFT(SUFFIX)\
434
    {\
435
        gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
436
        gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
437
        gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
438
        gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
439
        gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
440
        gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
441
        gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
442
        gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
443
    },\
444
    {\
445
        gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
446
        gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
447
        gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
448
        gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
449
        gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
450
        gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
451
        gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
452
        gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
453
    },\
454
    {\
455
        gen_op_roll ## SUFFIX ## _T0_T1_cc,\
456
        gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
457
        gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
458
        gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
459
        gen_op_shll ## SUFFIX ## _T0_T1_cc,\
460
        gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
461
        gen_op_shll ## SUFFIX ## _T0_T1_cc,\
462
        gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
463
    },
464

    
465
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
466
    DEF_SHIFT( )
467
};
468

    
469
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[9][8] = {
470
    DEF_SHIFT(_raw)
471
#ifndef CONFIG_USER_ONLY
472
    DEF_SHIFT(_kernel)
473
    DEF_SHIFT(_user)
474
#endif
475
};
476

    
477
#define DEF_SHIFTD(SUFFIX, op)\
478
    {\
479
        NULL,\
480
        NULL,\
481
    },\
482
    {\
483
        gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
484
        gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
485
    },\
486
    {\
487
        gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
488
        gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
489
    },
490

    
491

    
492
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[3][2] = {
493
    DEF_SHIFTD(, im)
494
};
495

    
496
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[3][2] = {
497
    DEF_SHIFTD(, ECX)
498
};
499

    
500
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[9][2] = {
501
    DEF_SHIFTD(_raw, im)
502
#ifndef CONFIG_USER_ONLY
503
    DEF_SHIFTD(_kernel, im)
504
    DEF_SHIFTD(_user, im)
505
#endif
506
};
507

    
508
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[9][2] = {
509
    DEF_SHIFTD(_raw, ECX)
510
#ifndef CONFIG_USER_ONLY
511
    DEF_SHIFTD(_kernel, ECX)
512
    DEF_SHIFTD(_user, ECX)
513
#endif
514
};
515

    
516
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
517
    [0] = {
518
        gen_op_btw_T0_T1_cc,
519
        gen_op_btsw_T0_T1_cc,
520
        gen_op_btrw_T0_T1_cc,
521
        gen_op_btcw_T0_T1_cc,
522
    },
523
    [1] = {
524
        gen_op_btl_T0_T1_cc,
525
        gen_op_btsl_T0_T1_cc,
526
        gen_op_btrl_T0_T1_cc,
527
        gen_op_btcl_T0_T1_cc,
528
    },
529
};
530

    
531
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
532
    [0] = {
533
        gen_op_bsfw_T0_cc,
534
        gen_op_bsrw_T0_cc,
535
    },
536
    [1] = {
537
        gen_op_bsfl_T0_cc,
538
        gen_op_bsrl_T0_cc,
539
    },
540
};
541

    
542
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
543
    gen_op_ldsb_raw_T0_A0,
544
    gen_op_ldsw_raw_T0_A0,
545
    NULL,
546
#ifndef CONFIG_USER_ONLY
547
    gen_op_ldsb_kernel_T0_A0,
548
    gen_op_ldsw_kernel_T0_A0,
549
    NULL,
550

    
551
    gen_op_ldsb_user_T0_A0,
552
    gen_op_ldsw_user_T0_A0,
553
    NULL,
554
#endif
555
};
556

    
557
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
558
    gen_op_ldub_raw_T0_A0,
559
    gen_op_lduw_raw_T0_A0,
560
    NULL,
561

    
562
#ifndef CONFIG_USER_ONLY
563
    gen_op_ldub_kernel_T0_A0,
564
    gen_op_lduw_kernel_T0_A0,
565
    NULL,
566

    
567
    gen_op_ldub_user_T0_A0,
568
    gen_op_lduw_user_T0_A0,
569
    NULL,
570
#endif
571
};
572

    
573
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
574
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
575
    gen_op_ldub_raw_T0_A0,
576
    gen_op_lduw_raw_T0_A0,
577
    gen_op_ldl_raw_T0_A0,
578

    
579
#ifndef CONFIG_USER_ONLY
580
    gen_op_ldub_kernel_T0_A0,
581
    gen_op_lduw_kernel_T0_A0,
582
    gen_op_ldl_kernel_T0_A0,
583

    
584
    gen_op_ldub_user_T0_A0,
585
    gen_op_lduw_user_T0_A0,
586
    gen_op_ldl_user_T0_A0,
587
#endif
588
};
589

    
590
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
591
    gen_op_ldub_raw_T1_A0,
592
    gen_op_lduw_raw_T1_A0,
593
    gen_op_ldl_raw_T1_A0,
594

    
595
#ifndef CONFIG_USER_ONLY
596
    gen_op_ldub_kernel_T1_A0,
597
    gen_op_lduw_kernel_T1_A0,
598
    gen_op_ldl_kernel_T1_A0,
599

    
600
    gen_op_ldub_user_T1_A0,
601
    gen_op_lduw_user_T1_A0,
602
    gen_op_ldl_user_T1_A0,
603
#endif
604
};
605

    
606
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
607
    gen_op_stb_raw_T0_A0,
608
    gen_op_stw_raw_T0_A0,
609
    gen_op_stl_raw_T0_A0,
610

    
611
#ifndef CONFIG_USER_ONLY
612
    gen_op_stb_kernel_T0_A0,
613
    gen_op_stw_kernel_T0_A0,
614
    gen_op_stl_kernel_T0_A0,
615

    
616
    gen_op_stb_user_T0_A0,
617
    gen_op_stw_user_T0_A0,
618
    gen_op_stl_user_T0_A0,
619
#endif
620
};
621

    
622
static GenOpFunc *gen_op_st_T1_A0[3 * 3] = {
623
    NULL,
624
    gen_op_stw_raw_T1_A0,
625
    gen_op_stl_raw_T1_A0,
626

    
627
#ifndef CONFIG_USER_ONLY
628
    NULL,
629
    gen_op_stw_kernel_T1_A0,
630
    gen_op_stl_kernel_T1_A0,
631

    
632
    NULL,
633
    gen_op_stw_user_T1_A0,
634
    gen_op_stl_user_T1_A0,
635
#endif
636
};
637

    
638
static inline void gen_string_movl_A0_ESI(DisasContext *s)
639
{
640
    int override;
641

    
642
    override = s->override;
643
    if (s->aflag) {
644
        /* 32 bit address */
645
        if (s->addseg && override < 0)
646
            override = R_DS;
647
        if (override >= 0) {
648
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
649
            gen_op_addl_A0_reg_sN[0][R_ESI]();
650
        } else {
651
            gen_op_movl_A0_reg[R_ESI]();
652
        }
653
    } else {
654
        /* 16 address, always override */
655
        if (override < 0)
656
            override = R_DS;
657
        gen_op_movl_A0_reg[R_ESI]();
658
        gen_op_andl_A0_ffff();
659
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
660
    }
661
}
662

    
663
static inline void gen_string_movl_A0_EDI(DisasContext *s)
664
{
665
    if (s->aflag) {
666
        if (s->addseg) {
667
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
668
            gen_op_addl_A0_reg_sN[0][R_EDI]();
669
        } else {
670
            gen_op_movl_A0_reg[R_EDI]();
671
        }
672
    } else {
673
        gen_op_movl_A0_reg[R_EDI]();
674
        gen_op_andl_A0_ffff();
675
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
676
    }
677
}
678

    
679
static GenOpFunc *gen_op_movl_T0_Dshift[3] = {
680
    gen_op_movl_T0_Dshiftb,
681
    gen_op_movl_T0_Dshiftw,
682
    gen_op_movl_T0_Dshiftl,
683
};
684

    
685
static GenOpFunc2 *gen_op_jz_ecx[2] = {
686
    gen_op_jz_ecxw,
687
    gen_op_jz_ecxl,
688
};
689
    
690
static GenOpFunc1 *gen_op_jz_ecx_im[2] = {
691
    gen_op_jz_ecxw_im,
692
    gen_op_jz_ecxl_im,
693
};
694

    
695
static GenOpFunc *gen_op_dec_ECX[2] = {
696
    gen_op_decw_ECX,
697
    gen_op_decl_ECX,
698
};
699

    
700
#ifdef USE_DIRECT_JUMP
701
typedef GenOpFunc GenOpFuncTB2;
702
#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot]()
703
#else
704
typedef GenOpFunc1 GenOpFuncTB2;
705
#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot](tb)
706
#endif
707

    
708
static GenOpFuncTB2 *gen_op_string_jnz_sub2[2][3] = {
709
    {
710
        gen_op_string_jnz_subb,
711
        gen_op_string_jnz_subw,
712
        gen_op_string_jnz_subl,
713
    },
714
    {
715
        gen_op_string_jz_subb,
716
        gen_op_string_jz_subw,
717
        gen_op_string_jz_subl,
718
    },
719
};
720

    
721
static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = {
722
    {
723
        gen_op_string_jnz_subb_im,
724
        gen_op_string_jnz_subw_im,
725
        gen_op_string_jnz_subl_im,
726
    },
727
    {
728
        gen_op_string_jz_subb_im,
729
        gen_op_string_jz_subw_im,
730
        gen_op_string_jz_subl_im,
731
    },
732
};
733

    
734
static GenOpFunc *gen_op_in_DX_T0[3] = {
735
    gen_op_inb_DX_T0,
736
    gen_op_inw_DX_T0,
737
    gen_op_inl_DX_T0,
738
};
739

    
740
static GenOpFunc *gen_op_out_DX_T0[3] = {
741
    gen_op_outb_DX_T0,
742
    gen_op_outw_DX_T0,
743
    gen_op_outl_DX_T0,
744
};
745

    
746
static GenOpFunc *gen_op_in[3] = {
747
    gen_op_inb_T0_T1,
748
    gen_op_inw_T0_T1,
749
    gen_op_inl_T0_T1,
750
};
751

    
752
static GenOpFunc *gen_op_out[3] = {
753
    gen_op_outb_T0_T1,
754
    gen_op_outw_T0_T1,
755
    gen_op_outl_T0_T1,
756
};
757

    
758
static GenOpFunc *gen_check_io_T0[3] = {
759
    gen_op_check_iob_T0,
760
    gen_op_check_iow_T0,
761
    gen_op_check_iol_T0,
762
};
763

    
764
static GenOpFunc *gen_check_io_DX[3] = {
765
    gen_op_check_iob_DX,
766
    gen_op_check_iow_DX,
767
    gen_op_check_iol_DX,
768
};
769

    
770
static void gen_check_io(DisasContext *s, int ot, int use_dx, int cur_eip)
771
{
772
    if (s->pe && (s->cpl > s->iopl || s->vm86)) {
773
        if (s->cc_op != CC_OP_DYNAMIC)
774
            gen_op_set_cc_op(s->cc_op);
775
        gen_op_jmp_im(cur_eip);
776
        if (use_dx)
777
            gen_check_io_DX[ot]();
778
        else
779
            gen_check_io_T0[ot]();
780
    }
781
}
782

    
783
static inline void gen_movs(DisasContext *s, int ot)
784
{
785
    gen_string_movl_A0_ESI(s);
786
    gen_op_ld_T0_A0[ot + s->mem_index]();
787
    gen_string_movl_A0_EDI(s);
788
    gen_op_st_T0_A0[ot + s->mem_index]();
789
    gen_op_movl_T0_Dshift[ot]();
790
    if (s->aflag) {
791
        gen_op_addl_ESI_T0();
792
        gen_op_addl_EDI_T0();
793
    } else {
794
        gen_op_addw_ESI_T0();
795
        gen_op_addw_EDI_T0();
796
    }
797
}
798

    
799
static inline void gen_update_cc_op(DisasContext *s)
800
{
801
    if (s->cc_op != CC_OP_DYNAMIC) {
802
        gen_op_set_cc_op(s->cc_op);
803
        s->cc_op = CC_OP_DYNAMIC;
804
    }
805
}
806

    
807
static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip)
808
{
809
    if (s->jmp_opt) {
810
        gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
811
    } else {
812
        /* XXX: does not work with gdbstub "ice" single step - not a
813
           serious problem */
814
        gen_op_jz_ecx_im[s->aflag](next_eip);
815
    }
816
}
817

    
818
static inline void gen_stos(DisasContext *s, int ot)
819
{
820
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
821
    gen_string_movl_A0_EDI(s);
822
    gen_op_st_T0_A0[ot + s->mem_index]();
823
    gen_op_movl_T0_Dshift[ot]();
824
    if (s->aflag) {
825
        gen_op_addl_EDI_T0();
826
    } else {
827
        gen_op_addw_EDI_T0();
828
    }
829
}
830

    
831
static inline void gen_lods(DisasContext *s, int ot)
832
{
833
    gen_string_movl_A0_ESI(s);
834
    gen_op_ld_T0_A0[ot + s->mem_index]();
835
    gen_op_mov_reg_T0[ot][R_EAX]();
836
    gen_op_movl_T0_Dshift[ot]();
837
    if (s->aflag) {
838
        gen_op_addl_ESI_T0();
839
    } else {
840
        gen_op_addw_ESI_T0();
841
    }
842
}
843

    
844
static inline void gen_scas(DisasContext *s, int ot)
845
{
846
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
847
    gen_string_movl_A0_EDI(s);
848
    gen_op_ld_T1_A0[ot + s->mem_index]();
849
    gen_op_cmpl_T0_T1_cc();
850
    gen_op_movl_T0_Dshift[ot]();
851
    if (s->aflag) {
852
        gen_op_addl_EDI_T0();
853
    } else {
854
        gen_op_addw_EDI_T0();
855
    }
856
}
857

    
858
static inline void gen_cmps(DisasContext *s, int ot)
859
{
860
    gen_string_movl_A0_ESI(s);
861
    gen_op_ld_T0_A0[ot + s->mem_index]();
862
    gen_string_movl_A0_EDI(s);
863
    gen_op_ld_T1_A0[ot + s->mem_index]();
864
    gen_op_cmpl_T0_T1_cc();
865
    gen_op_movl_T0_Dshift[ot]();
866
    if (s->aflag) {
867
        gen_op_addl_ESI_T0();
868
        gen_op_addl_EDI_T0();
869
    } else {
870
        gen_op_addw_ESI_T0();
871
        gen_op_addw_EDI_T0();
872
    }
873
}
874

    
875
static inline void gen_ins(DisasContext *s, int ot)
876
{
877
    gen_string_movl_A0_EDI(s);
878
    gen_op_movl_T0_0();
879
    gen_op_st_T0_A0[ot + s->mem_index]();
880
    gen_op_in_DX_T0[ot]();
881
    gen_op_st_T0_A0[ot + s->mem_index]();
882
    gen_op_movl_T0_Dshift[ot]();
883
    if (s->aflag) {
884
        gen_op_addl_EDI_T0();
885
    } else {
886
        gen_op_addw_EDI_T0();
887
    }
888
}
889

    
890
static inline void gen_outs(DisasContext *s, int ot)
891
{
892
    gen_string_movl_A0_ESI(s);
893
    gen_op_ld_T0_A0[ot + s->mem_index]();
894
    gen_op_out_DX_T0[ot]();
895
    gen_op_movl_T0_Dshift[ot]();
896
    if (s->aflag) {
897
        gen_op_addl_ESI_T0();
898
    } else {
899
        gen_op_addw_ESI_T0();
900
    }
901
}
902

    
903
/* same method as Valgrind : we generate jumps to current or next
904
   instruction */
905
#define GEN_REPZ(op)                                                          \
906
static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
907
                                 unsigned int cur_eip, unsigned int next_eip) \
908
{                                                                             \
909
    gen_update_cc_op(s);                                                      \
910
    gen_jz_ecx_string(s, next_eip);                                           \
911
    gen_ ## op(s, ot);                                                        \
912
    gen_op_dec_ECX[s->aflag]();                                               \
913
    /* a loop would cause two single step exceptions if ECX = 1               \
914
       before rep string_insn */                                              \
915
    if (!s->jmp_opt)                                                          \
916
        gen_op_jz_ecx_im[s->aflag](next_eip);                                 \
917
    gen_jmp(s, cur_eip);                                                      \
918
}
919

    
920
#define GEN_REPZ2(op)                                                         \
921
static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
922
                                   unsigned int cur_eip,                      \
923
                                   unsigned int next_eip,                     \
924
                                   int nz)                                    \
925
{                                                                             \
926
    gen_update_cc_op(s);                                                      \
927
    gen_jz_ecx_string(s, next_eip);                                           \
928
    gen_ ## op(s, ot);                                                        \
929
    gen_op_dec_ECX[s->aflag]();                                               \
930
    gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
931
    if (!s->jmp_opt)                                                          \
932
        gen_op_string_jnz_sub_im[nz][ot](next_eip);                           \
933
    else                                                                      \
934
        gen_op_string_jnz_sub(nz, ot, (long)s->tb);                           \
935
    if (!s->jmp_opt)                                                          \
936
        gen_op_jz_ecx_im[s->aflag](next_eip);                                 \
937
    gen_jmp(s, cur_eip);                                                      \
938
}
939

    
940
GEN_REPZ(movs)
941
GEN_REPZ(stos)
942
GEN_REPZ(lods)
943
GEN_REPZ(ins)
944
GEN_REPZ(outs)
945
GEN_REPZ2(scas)
946
GEN_REPZ2(cmps)
947

    
948
enum {
949
    JCC_O,
950
    JCC_B,
951
    JCC_Z,
952
    JCC_BE,
953
    JCC_S,
954
    JCC_P,
955
    JCC_L,
956
    JCC_LE,
957
};
958

    
959
static GenOpFunc3 *gen_jcc_sub[3][8] = {
960
    [OT_BYTE] = {
961
        NULL,
962
        gen_op_jb_subb,
963
        gen_op_jz_subb,
964
        gen_op_jbe_subb,
965
        gen_op_js_subb,
966
        NULL,
967
        gen_op_jl_subb,
968
        gen_op_jle_subb,
969
    },
970
    [OT_WORD] = {
971
        NULL,
972
        gen_op_jb_subw,
973
        gen_op_jz_subw,
974
        gen_op_jbe_subw,
975
        gen_op_js_subw,
976
        NULL,
977
        gen_op_jl_subw,
978
        gen_op_jle_subw,
979
    },
980
    [OT_LONG] = {
981
        NULL,
982
        gen_op_jb_subl,
983
        gen_op_jz_subl,
984
        gen_op_jbe_subl,
985
        gen_op_js_subl,
986
        NULL,
987
        gen_op_jl_subl,
988
        gen_op_jle_subl,
989
    },
990
};
991
static GenOpFunc2 *gen_op_loop[2][4] = {
992
    [0] = {
993
        gen_op_loopnzw,
994
        gen_op_loopzw,
995
        gen_op_loopw,
996
        gen_op_jecxzw,
997
    },
998
    [1] = {
999
        gen_op_loopnzl,
1000
        gen_op_loopzl,
1001
        gen_op_loopl,
1002
        gen_op_jecxzl,
1003
    },
1004
};
1005

    
1006
static GenOpFunc *gen_setcc_slow[8] = {
1007
    gen_op_seto_T0_cc,
1008
    gen_op_setb_T0_cc,
1009
    gen_op_setz_T0_cc,
1010
    gen_op_setbe_T0_cc,
1011
    gen_op_sets_T0_cc,
1012
    gen_op_setp_T0_cc,
1013
    gen_op_setl_T0_cc,
1014
    gen_op_setle_T0_cc,
1015
};
1016

    
1017
static GenOpFunc *gen_setcc_sub[3][8] = {
1018
    [OT_BYTE] = {
1019
        NULL,
1020
        gen_op_setb_T0_subb,
1021
        gen_op_setz_T0_subb,
1022
        gen_op_setbe_T0_subb,
1023
        gen_op_sets_T0_subb,
1024
        NULL,
1025
        gen_op_setl_T0_subb,
1026
        gen_op_setle_T0_subb,
1027
    },
1028
    [OT_WORD] = {
1029
        NULL,
1030
        gen_op_setb_T0_subw,
1031
        gen_op_setz_T0_subw,
1032
        gen_op_setbe_T0_subw,
1033
        gen_op_sets_T0_subw,
1034
        NULL,
1035
        gen_op_setl_T0_subw,
1036
        gen_op_setle_T0_subw,
1037
    },
1038
    [OT_LONG] = {
1039
        NULL,
1040
        gen_op_setb_T0_subl,
1041
        gen_op_setz_T0_subl,
1042
        gen_op_setbe_T0_subl,
1043
        gen_op_sets_T0_subl,
1044
        NULL,
1045
        gen_op_setl_T0_subl,
1046
        gen_op_setle_T0_subl,
1047
    },
1048
};
1049

    
1050
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1051
    gen_op_fadd_ST0_FT0,
1052
    gen_op_fmul_ST0_FT0,
1053
    gen_op_fcom_ST0_FT0,
1054
    gen_op_fcom_ST0_FT0,
1055
    gen_op_fsub_ST0_FT0,
1056
    gen_op_fsubr_ST0_FT0,
1057
    gen_op_fdiv_ST0_FT0,
1058
    gen_op_fdivr_ST0_FT0,
1059
};
1060

    
1061
/* NOTE the exception in "r" op ordering */
1062
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1063
    gen_op_fadd_STN_ST0,
1064
    gen_op_fmul_STN_ST0,
1065
    NULL,
1066
    NULL,
1067
    gen_op_fsubr_STN_ST0,
1068
    gen_op_fsub_STN_ST0,
1069
    gen_op_fdivr_STN_ST0,
1070
    gen_op_fdiv_STN_ST0,
1071
};
1072

    
1073
/* if d == OR_TMP0, it means memory operand (address in A0) */
1074
static void gen_op(DisasContext *s1, int op, int ot, int d)
1075
{
1076
    GenOpFunc *gen_update_cc;
1077
    
1078
    if (d != OR_TMP0) {
1079
        gen_op_mov_TN_reg[ot][0][d]();
1080
    } else {
1081
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1082
    }
1083
    switch(op) {
1084
    case OP_ADCL:
1085
    case OP_SBBL:
1086
        if (s1->cc_op != CC_OP_DYNAMIC)
1087
            gen_op_set_cc_op(s1->cc_op);
1088
        if (d != OR_TMP0) {
1089
            gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1090
            gen_op_mov_reg_T0[ot][d]();
1091
        } else {
1092
            gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
1093
        }
1094
        s1->cc_op = CC_OP_DYNAMIC;
1095
        goto the_end;
1096
    case OP_ADDL:
1097
        gen_op_addl_T0_T1();
1098
        s1->cc_op = CC_OP_ADDB + ot;
1099
        gen_update_cc = gen_op_update2_cc;
1100
        break;
1101
    case OP_SUBL:
1102
        gen_op_subl_T0_T1();
1103
        s1->cc_op = CC_OP_SUBB + ot;
1104
        gen_update_cc = gen_op_update2_cc;
1105
        break;
1106
    default:
1107
    case OP_ANDL:
1108
    case OP_ORL:
1109
    case OP_XORL:
1110
        gen_op_arith_T0_T1_cc[op]();
1111
        s1->cc_op = CC_OP_LOGICB + ot;
1112
        gen_update_cc = gen_op_update1_cc;
1113
        break;
1114
    case OP_CMPL:
1115
        gen_op_cmpl_T0_T1_cc();
1116
        s1->cc_op = CC_OP_SUBB + ot;
1117
        gen_update_cc = NULL;
1118
        break;
1119
    }
1120
    if (op != OP_CMPL) {
1121
        if (d != OR_TMP0)
1122
            gen_op_mov_reg_T0[ot][d]();
1123
        else
1124
            gen_op_st_T0_A0[ot + s1->mem_index]();
1125
    }
1126
    /* the flags update must happen after the memory write (precise
1127
       exception support) */
1128
    if (gen_update_cc)
1129
        gen_update_cc();
1130
 the_end: ;
1131
}
1132

    
1133
/* if d == OR_TMP0, it means memory operand (address in A0) */
1134
static void gen_inc(DisasContext *s1, int ot, int d, int c)
1135
{
1136
    if (d != OR_TMP0)
1137
        gen_op_mov_TN_reg[ot][0][d]();
1138
    else
1139
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1140
    if (s1->cc_op != CC_OP_DYNAMIC)
1141
        gen_op_set_cc_op(s1->cc_op);
1142
    if (c > 0) {
1143
        gen_op_incl_T0();
1144
        s1->cc_op = CC_OP_INCB + ot;
1145
    } else {
1146
        gen_op_decl_T0();
1147
        s1->cc_op = CC_OP_DECB + ot;
1148
    }
1149
    if (d != OR_TMP0)
1150
        gen_op_mov_reg_T0[ot][d]();
1151
    else
1152
        gen_op_st_T0_A0[ot + s1->mem_index]();
1153
    gen_op_update_inc_cc();
1154
}
1155

    
1156
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1157
{
1158
    if (d != OR_TMP0)
1159
        gen_op_mov_TN_reg[ot][0][d]();
1160
    else
1161
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1162
    if (s != OR_TMP1)
1163
        gen_op_mov_TN_reg[ot][1][s]();
1164
    /* for zero counts, flags are not updated, so must do it dynamically */
1165
    if (s1->cc_op != CC_OP_DYNAMIC)
1166
        gen_op_set_cc_op(s1->cc_op);
1167
    
1168
    if (d != OR_TMP0)
1169
        gen_op_shift_T0_T1_cc[ot][op]();
1170
    else
1171
        gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
1172
    if (d != OR_TMP0)
1173
        gen_op_mov_reg_T0[ot][d]();
1174
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1175
}
1176

    
1177
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1178
{
1179
    /* currently not optimized */
1180
    gen_op_movl_T1_im(c);
1181
    gen_shift(s1, op, ot, d, OR_TMP1);
1182
}
1183

    
1184
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1185
{
1186
    int havesib;
1187
    int base, disp;
1188
    int index;
1189
    int scale;
1190
    int opreg;
1191
    int mod, rm, code, override, must_add_seg;
1192

    
1193
    override = s->override;
1194
    must_add_seg = s->addseg;
1195
    if (override >= 0)
1196
        must_add_seg = 1;
1197
    mod = (modrm >> 6) & 3;
1198
    rm = modrm & 7;
1199

    
1200
    if (s->aflag) {
1201

    
1202
        havesib = 0;
1203
        base = rm;
1204
        index = 0;
1205
        scale = 0;
1206
        
1207
        if (base == 4) {
1208
            havesib = 1;
1209
            code = ldub_code(s->pc++);
1210
            scale = (code >> 6) & 3;
1211
            index = (code >> 3) & 7;
1212
            base = code & 7;
1213
        }
1214

    
1215
        switch (mod) {
1216
        case 0:
1217
            if (base == 5) {
1218
                base = -1;
1219
                disp = ldl_code(s->pc);
1220
                s->pc += 4;
1221
            } else {
1222
                disp = 0;
1223
            }
1224
            break;
1225
        case 1:
1226
            disp = (int8_t)ldub_code(s->pc++);
1227
            break;
1228
        default:
1229
        case 2:
1230
            disp = ldl_code(s->pc);
1231
            s->pc += 4;
1232
            break;
1233
        }
1234
        
1235
        if (base >= 0) {
1236
            /* for correct popl handling with esp */
1237
            if (base == 4 && s->popl_esp_hack)
1238
                disp += s->popl_esp_hack;
1239
            gen_op_movl_A0_reg[base]();
1240
            if (disp != 0)
1241
                gen_op_addl_A0_im(disp);
1242
        } else {
1243
            gen_op_movl_A0_im(disp);
1244
        }
1245
        /* XXX: index == 4 is always invalid */
1246
        if (havesib && (index != 4 || scale != 0)) {
1247
            gen_op_addl_A0_reg_sN[scale][index]();
1248
        }
1249
        if (must_add_seg) {
1250
            if (override < 0) {
1251
                if (base == R_EBP || base == R_ESP)
1252
                    override = R_SS;
1253
                else
1254
                    override = R_DS;
1255
            }
1256
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1257
        }
1258
    } else {
1259
        switch (mod) {
1260
        case 0:
1261
            if (rm == 6) {
1262
                disp = lduw_code(s->pc);
1263
                s->pc += 2;
1264
                gen_op_movl_A0_im(disp);
1265
                rm = 0; /* avoid SS override */
1266
                goto no_rm;
1267
            } else {
1268
                disp = 0;
1269
            }
1270
            break;
1271
        case 1:
1272
            disp = (int8_t)ldub_code(s->pc++);
1273
            break;
1274
        default:
1275
        case 2:
1276
            disp = lduw_code(s->pc);
1277
            s->pc += 2;
1278
            break;
1279
        }
1280
        switch(rm) {
1281
        case 0:
1282
            gen_op_movl_A0_reg[R_EBX]();
1283
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1284
            break;
1285
        case 1:
1286
            gen_op_movl_A0_reg[R_EBX]();
1287
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1288
            break;
1289
        case 2:
1290
            gen_op_movl_A0_reg[R_EBP]();
1291
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1292
            break;
1293
        case 3:
1294
            gen_op_movl_A0_reg[R_EBP]();
1295
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1296
            break;
1297
        case 4:
1298
            gen_op_movl_A0_reg[R_ESI]();
1299
            break;
1300
        case 5:
1301
            gen_op_movl_A0_reg[R_EDI]();
1302
            break;
1303
        case 6:
1304
            gen_op_movl_A0_reg[R_EBP]();
1305
            break;
1306
        default:
1307
        case 7:
1308
            gen_op_movl_A0_reg[R_EBX]();
1309
            break;
1310
        }
1311
        if (disp != 0)
1312
            gen_op_addl_A0_im(disp);
1313
        gen_op_andl_A0_ffff();
1314
    no_rm:
1315
        if (must_add_seg) {
1316
            if (override < 0) {
1317
                if (rm == 2 || rm == 3 || rm == 6)
1318
                    override = R_SS;
1319
                else
1320
                    override = R_DS;
1321
            }
1322
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1323
        }
1324
    }
1325

    
1326
    opreg = OR_A0;
1327
    disp = 0;
1328
    *reg_ptr = opreg;
1329
    *offset_ptr = disp;
1330
}
1331

    
1332
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1333
   OR_TMP0 */
1334
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1335
{
1336
    int mod, rm, opreg, disp;
1337

    
1338
    mod = (modrm >> 6) & 3;
1339
    rm = modrm & 7;
1340
    if (mod == 3) {
1341
        if (is_store) {
1342
            if (reg != OR_TMP0)
1343
                gen_op_mov_TN_reg[ot][0][reg]();
1344
            gen_op_mov_reg_T0[ot][rm]();
1345
        } else {
1346
            gen_op_mov_TN_reg[ot][0][rm]();
1347
            if (reg != OR_TMP0)
1348
                gen_op_mov_reg_T0[ot][reg]();
1349
        }
1350
    } else {
1351
        gen_lea_modrm(s, modrm, &opreg, &disp);
1352
        if (is_store) {
1353
            if (reg != OR_TMP0)
1354
                gen_op_mov_TN_reg[ot][0][reg]();
1355
            gen_op_st_T0_A0[ot + s->mem_index]();
1356
        } else {
1357
            gen_op_ld_T0_A0[ot + s->mem_index]();
1358
            if (reg != OR_TMP0)
1359
                gen_op_mov_reg_T0[ot][reg]();
1360
        }
1361
    }
1362
}
1363

    
1364
static inline uint32_t insn_get(DisasContext *s, int ot)
1365
{
1366
    uint32_t ret;
1367

    
1368
    switch(ot) {
1369
    case OT_BYTE:
1370
        ret = ldub_code(s->pc);
1371
        s->pc++;
1372
        break;
1373
    case OT_WORD:
1374
        ret = lduw_code(s->pc);
1375
        s->pc += 2;
1376
        break;
1377
    default:
1378
    case OT_LONG:
1379
        ret = ldl_code(s->pc);
1380
        s->pc += 4;
1381
        break;
1382
    }
1383
    return ret;
1384
}
1385

    
1386
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1387
{
1388
    TranslationBlock *tb;
1389
    int inv, jcc_op;
1390
    GenOpFunc3 *func;
1391

    
1392
    inv = b & 1;
1393
    jcc_op = (b >> 1) & 7;
1394
    
1395
    if (s->jmp_opt) {
1396
        switch(s->cc_op) {
1397
            /* we optimize the cmp/jcc case */
1398
        case CC_OP_SUBB:
1399
        case CC_OP_SUBW:
1400
        case CC_OP_SUBL:
1401
            func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1402
            break;
1403
            
1404
            /* some jumps are easy to compute */
1405
        case CC_OP_ADDB:
1406
        case CC_OP_ADDW:
1407
        case CC_OP_ADDL:
1408
        case CC_OP_ADCB:
1409
        case CC_OP_ADCW:
1410
        case CC_OP_ADCL:
1411
        case CC_OP_SBBB:
1412
        case CC_OP_SBBW:
1413
        case CC_OP_SBBL:
1414
        case CC_OP_LOGICB:
1415
        case CC_OP_LOGICW:
1416
        case CC_OP_LOGICL:
1417
        case CC_OP_INCB:
1418
        case CC_OP_INCW:
1419
        case CC_OP_INCL:
1420
        case CC_OP_DECB:
1421
        case CC_OP_DECW:
1422
        case CC_OP_DECL:
1423
        case CC_OP_SHLB:
1424
        case CC_OP_SHLW:
1425
        case CC_OP_SHLL:
1426
        case CC_OP_SARB:
1427
        case CC_OP_SARW:
1428
        case CC_OP_SARL:
1429
            switch(jcc_op) {
1430
            case JCC_Z:
1431
                func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1432
                break;
1433
            case JCC_S:
1434
                func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1435
                break;
1436
            default:
1437
                func = NULL;
1438
                break;
1439
            }
1440
            break;
1441
        default:
1442
            func = NULL;
1443
            break;
1444
        }
1445

    
1446
        if (s->cc_op != CC_OP_DYNAMIC)
1447
            gen_op_set_cc_op(s->cc_op);
1448

    
1449
        if (!func) {
1450
            gen_setcc_slow[jcc_op]();
1451
            func = gen_op_jcc;
1452
        }
1453
    
1454
        tb = s->tb;
1455
        if (!inv) {
1456
            func((long)tb, val, next_eip);
1457
        } else {
1458
            func((long)tb, next_eip, val);
1459
        }
1460
        s->is_jmp = 3;
1461
    } else {
1462
        if (s->cc_op != CC_OP_DYNAMIC) {
1463
            gen_op_set_cc_op(s->cc_op);
1464
            s->cc_op = CC_OP_DYNAMIC;
1465
        }
1466
        gen_setcc_slow[jcc_op]();
1467
        if (!inv) {
1468
            gen_op_jcc_im(val, next_eip);
1469
        } else {
1470
            gen_op_jcc_im(next_eip, val);
1471
        }
1472
        gen_eob(s);
1473
    }
1474
}
1475

    
1476
static void gen_setcc(DisasContext *s, int b)
1477
{
1478
    int inv, jcc_op;
1479
    GenOpFunc *func;
1480

    
1481
    inv = b & 1;
1482
    jcc_op = (b >> 1) & 7;
1483
    switch(s->cc_op) {
1484
        /* we optimize the cmp/jcc case */
1485
    case CC_OP_SUBB:
1486
    case CC_OP_SUBW:
1487
    case CC_OP_SUBL:
1488
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1489
        if (!func)
1490
            goto slow_jcc;
1491
        break;
1492
        
1493
        /* some jumps are easy to compute */
1494
    case CC_OP_ADDB:
1495
    case CC_OP_ADDW:
1496
    case CC_OP_ADDL:
1497
    case CC_OP_LOGICB:
1498
    case CC_OP_LOGICW:
1499
    case CC_OP_LOGICL:
1500
    case CC_OP_INCB:
1501
    case CC_OP_INCW:
1502
    case CC_OP_INCL:
1503
    case CC_OP_DECB:
1504
    case CC_OP_DECW:
1505
    case CC_OP_DECL:
1506
    case CC_OP_SHLB:
1507
    case CC_OP_SHLW:
1508
    case CC_OP_SHLL:
1509
        switch(jcc_op) {
1510
        case JCC_Z:
1511
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1512
            break;
1513
        case JCC_S:
1514
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1515
            break;
1516
        default:
1517
            goto slow_jcc;
1518
        }
1519
        break;
1520
    default:
1521
    slow_jcc:
1522
        if (s->cc_op != CC_OP_DYNAMIC)
1523
            gen_op_set_cc_op(s->cc_op);
1524
        func = gen_setcc_slow[jcc_op];
1525
        break;
1526
    }
1527
    func();
1528
    if (inv) {
1529
        gen_op_xor_T0_1();
1530
    }
1531
}
1532

    
1533
/* move T0 to seg_reg and compute if the CPU state may change. Never
1534
   call this function with seg_reg == R_CS */
1535
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1536
{
1537
    if (s->pe && !s->vm86) {
1538
        /* XXX: optimize by finding processor state dynamically */
1539
        if (s->cc_op != CC_OP_DYNAMIC)
1540
            gen_op_set_cc_op(s->cc_op);
1541
        gen_op_jmp_im(cur_eip);
1542
        gen_op_movl_seg_T0(seg_reg);
1543
        /* abort translation because the addseg value may change or
1544
           because ss32 may change. For R_SS, translation must always
1545
           stop as a special handling must be done to disable hardware
1546
           interrupts for the next instruction */
1547
        if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1548
            s->is_jmp = 3;
1549
    } else {
1550
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1551
        if (seg_reg == R_SS)
1552
            s->is_jmp = 3;
1553
    }
1554
}
1555

    
1556
static inline void gen_stack_update(DisasContext *s, int addend)
1557
{
1558
    if (s->ss32) {
1559
        if (addend == 2)
1560
            gen_op_addl_ESP_2();
1561
        else if (addend == 4)
1562
            gen_op_addl_ESP_4();
1563
        else 
1564
            gen_op_addl_ESP_im(addend);
1565
    } else {
1566
        if (addend == 2)
1567
            gen_op_addw_ESP_2();
1568
        else if (addend == 4)
1569
            gen_op_addw_ESP_4();
1570
        else
1571
            gen_op_addw_ESP_im(addend);
1572
    }
1573
}
1574

    
1575
/* generate a push. It depends on ss32, addseg and dflag */
1576
static void gen_push_T0(DisasContext *s)
1577
{
1578
    gen_op_movl_A0_reg[R_ESP]();
1579
    if (!s->dflag)
1580
        gen_op_subl_A0_2();
1581
    else
1582
        gen_op_subl_A0_4();
1583
    if (s->ss32) {
1584
        if (s->addseg) {
1585
            gen_op_movl_T1_A0();
1586
            gen_op_addl_A0_SS();
1587
        }
1588
    } else {
1589
        gen_op_andl_A0_ffff();
1590
        gen_op_movl_T1_A0();
1591
        gen_op_addl_A0_SS();
1592
    }
1593
    gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
1594
    if (s->ss32 && !s->addseg)
1595
        gen_op_movl_ESP_A0();
1596
    else
1597
        gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
1598
}
1599

    
1600
/* generate a push. It depends on ss32, addseg and dflag */
1601
/* slower version for T1, only used for call Ev */
1602
static void gen_push_T1(DisasContext *s)
1603
{
1604
    gen_op_movl_A0_reg[R_ESP]();
1605
    if (!s->dflag)
1606
        gen_op_subl_A0_2();
1607
    else
1608
        gen_op_subl_A0_4();
1609
    if (s->ss32) {
1610
        if (s->addseg) {
1611
            gen_op_addl_A0_SS();
1612
        }
1613
    } else {
1614
        gen_op_andl_A0_ffff();
1615
        gen_op_addl_A0_SS();
1616
    }
1617
    gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
1618
    
1619
    if (s->ss32 && !s->addseg)
1620
        gen_op_movl_ESP_A0();
1621
    else
1622
        gen_stack_update(s, (-2) << s->dflag);
1623
}
1624

    
1625
/* two step pop is necessary for precise exceptions */
1626
static void gen_pop_T0(DisasContext *s)
1627
{
1628
    gen_op_movl_A0_reg[R_ESP]();
1629
    if (s->ss32) {
1630
        if (s->addseg)
1631
            gen_op_addl_A0_SS();
1632
    } else {
1633
        gen_op_andl_A0_ffff();
1634
        gen_op_addl_A0_SS();
1635
    }
1636
    gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
1637
}
1638

    
1639
static void gen_pop_update(DisasContext *s)
1640
{
1641
    gen_stack_update(s, 2 << s->dflag);
1642
}
1643

    
1644
static void gen_stack_A0(DisasContext *s)
1645
{
1646
    gen_op_movl_A0_ESP();
1647
    if (!s->ss32)
1648
        gen_op_andl_A0_ffff();
1649
    gen_op_movl_T1_A0();
1650
    if (s->addseg)
1651
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1652
}
1653

    
1654
/* NOTE: wrap around in 16 bit not fully handled */
1655
static void gen_pusha(DisasContext *s)
1656
{
1657
    int i;
1658
    gen_op_movl_A0_ESP();
1659
    gen_op_addl_A0_im(-16 <<  s->dflag);
1660
    if (!s->ss32)
1661
        gen_op_andl_A0_ffff();
1662
    gen_op_movl_T1_A0();
1663
    if (s->addseg)
1664
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1665
    for(i = 0;i < 8; i++) {
1666
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1667
        gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
1668
        gen_op_addl_A0_im(2 <<  s->dflag);
1669
    }
1670
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1671
}
1672

    
1673
/* NOTE: wrap around in 16 bit not fully handled */
1674
static void gen_popa(DisasContext *s)
1675
{
1676
    int i;
1677
    gen_op_movl_A0_ESP();
1678
    if (!s->ss32)
1679
        gen_op_andl_A0_ffff();
1680
    gen_op_movl_T1_A0();
1681
    gen_op_addl_T1_im(16 <<  s->dflag);
1682
    if (s->addseg)
1683
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1684
    for(i = 0;i < 8; i++) {
1685
        /* ESP is not reloaded */
1686
        if (i != 3) {
1687
            gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
1688
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1689
        }
1690
        gen_op_addl_A0_im(2 <<  s->dflag);
1691
    }
1692
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1693
}
1694

    
1695
static void gen_enter(DisasContext *s, int esp_addend, int level)
1696
{
1697
    int ot, opsize;
1698

    
1699
    ot = s->dflag + OT_WORD;
1700
    level &= 0x1f;
1701
    opsize = 2 << s->dflag;
1702

    
1703
    gen_op_movl_A0_ESP();
1704
    gen_op_addl_A0_im(-opsize);
1705
    if (!s->ss32)
1706
        gen_op_andl_A0_ffff();
1707
    gen_op_movl_T1_A0();
1708
    if (s->addseg)
1709
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1710
    /* push bp */
1711
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1712
    gen_op_st_T0_A0[ot + s->mem_index]();
1713
    if (level) {
1714
        gen_op_enter_level(level, s->dflag);
1715
    }
1716
    gen_op_mov_reg_T1[ot][R_EBP]();
1717
    gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
1718
    gen_op_mov_reg_T1[ot][R_ESP]();
1719
}
1720

    
1721
static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1722
{
1723
    if (s->cc_op != CC_OP_DYNAMIC)
1724
        gen_op_set_cc_op(s->cc_op);
1725
    gen_op_jmp_im(cur_eip);
1726
    gen_op_raise_exception(trapno);
1727
    s->is_jmp = 3;
1728
}
1729

    
1730
/* an interrupt is different from an exception because of the
1731
   priviledge checks */
1732
static void gen_interrupt(DisasContext *s, int intno, 
1733
                          unsigned int cur_eip, unsigned int next_eip)
1734
{
1735
    if (s->cc_op != CC_OP_DYNAMIC)
1736
        gen_op_set_cc_op(s->cc_op);
1737
    gen_op_jmp_im(cur_eip);
1738
    gen_op_raise_interrupt(intno, next_eip);
1739
    s->is_jmp = 3;
1740
}
1741

    
1742
static void gen_debug(DisasContext *s, unsigned int cur_eip)
1743
{
1744
    if (s->cc_op != CC_OP_DYNAMIC)
1745
        gen_op_set_cc_op(s->cc_op);
1746
    gen_op_jmp_im(cur_eip);
1747
    gen_op_debug();
1748
    s->is_jmp = 3;
1749
}
1750

    
1751
/* generate a generic end of block. Trace exception is also generated
1752
   if needed */
1753
static void gen_eob(DisasContext *s)
1754
{
1755
    if (s->cc_op != CC_OP_DYNAMIC)
1756
        gen_op_set_cc_op(s->cc_op);
1757
    if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
1758
        gen_op_reset_inhibit_irq();
1759
    }
1760
    if (s->singlestep_enabled) {
1761
        gen_op_debug();
1762
    } else if (s->tf) {
1763
        gen_op_raise_exception(EXCP01_SSTP);
1764
    } else {
1765
        gen_op_movl_T0_0();
1766
        gen_op_exit_tb();
1767
    }
1768
    s->is_jmp = 3;
1769
}
1770

    
1771
/* generate a jump to eip. No segment change must happen before as a
1772
   direct call to the next block may occur */
1773
static void gen_jmp(DisasContext *s, unsigned int eip)
1774
{
1775
    TranslationBlock *tb = s->tb;
1776

    
1777
    if (s->jmp_opt) {
1778
        if (s->cc_op != CC_OP_DYNAMIC)
1779
            gen_op_set_cc_op(s->cc_op);
1780
        gen_op_jmp((long)tb, eip);
1781
        s->is_jmp = 3;
1782
    } else {
1783
        gen_op_jmp_im(eip);
1784
        gen_eob(s);
1785
    }
1786
}
1787

    
1788
/* convert one instruction. s->is_jmp is set if the translation must
1789
   be stopped. Return the next pc value */
1790
static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
1791
{
1792
    int b, prefixes, aflag, dflag;
1793
    int shift, ot;
1794
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1795
    unsigned int next_eip;
1796

    
1797
    s->pc = pc_start;
1798
    prefixes = 0;
1799
    aflag = s->code32;
1800
    dflag = s->code32;
1801
    s->override = -1;
1802
 next_byte:
1803
    b = ldub_code(s->pc);
1804
    s->pc++;
1805
    /* check prefixes */
1806
    switch (b) {
1807
    case 0xf3:
1808
        prefixes |= PREFIX_REPZ;
1809
        goto next_byte;
1810
    case 0xf2:
1811
        prefixes |= PREFIX_REPNZ;
1812
        goto next_byte;
1813
    case 0xf0:
1814
        prefixes |= PREFIX_LOCK;
1815
        goto next_byte;
1816
    case 0x2e:
1817
        s->override = R_CS;
1818
        goto next_byte;
1819
    case 0x36:
1820
        s->override = R_SS;
1821
        goto next_byte;
1822
    case 0x3e:
1823
        s->override = R_DS;
1824
        goto next_byte;
1825
    case 0x26:
1826
        s->override = R_ES;
1827
        goto next_byte;
1828
    case 0x64:
1829
        s->override = R_FS;
1830
        goto next_byte;
1831
    case 0x65:
1832
        s->override = R_GS;
1833
        goto next_byte;
1834
    case 0x66:
1835
        prefixes |= PREFIX_DATA;
1836
        goto next_byte;
1837
    case 0x67:
1838
        prefixes |= PREFIX_ADR;
1839
        goto next_byte;
1840
    }
1841

    
1842
    if (prefixes & PREFIX_DATA)
1843
        dflag ^= 1;
1844
    if (prefixes & PREFIX_ADR)
1845
        aflag ^= 1;
1846

    
1847
    s->prefix = prefixes;
1848
    s->aflag = aflag;
1849
    s->dflag = dflag;
1850

    
1851
    /* lock generation */
1852
    if (prefixes & PREFIX_LOCK)
1853
        gen_op_lock();
1854

    
1855
    /* now check op code */
1856
 reswitch:
1857
    switch(b) {
1858
    case 0x0f:
1859
        /**************************/
1860
        /* extended op code */
1861
        b = ldub_code(s->pc++) | 0x100;
1862
        goto reswitch;
1863
        
1864
        /**************************/
1865
        /* arith & logic */
1866
    case 0x00 ... 0x05:
1867
    case 0x08 ... 0x0d:
1868
    case 0x10 ... 0x15:
1869
    case 0x18 ... 0x1d:
1870
    case 0x20 ... 0x25:
1871
    case 0x28 ... 0x2d:
1872
    case 0x30 ... 0x35:
1873
    case 0x38 ... 0x3d:
1874
        {
1875
            int op, f, val;
1876
            op = (b >> 3) & 7;
1877
            f = (b >> 1) & 3;
1878

    
1879
            if ((b & 1) == 0)
1880
                ot = OT_BYTE;
1881
            else
1882
                ot = dflag ? OT_LONG : OT_WORD;
1883
            
1884
            switch(f) {
1885
            case 0: /* OP Ev, Gv */
1886
                modrm = ldub_code(s->pc++);
1887
                reg = ((modrm >> 3) & 7);
1888
                mod = (modrm >> 6) & 3;
1889
                rm = modrm & 7;
1890
                if (mod != 3) {
1891
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1892
                    opreg = OR_TMP0;
1893
                } else if (op == OP_XORL && rm == reg) {
1894
                xor_zero:
1895
                    /* xor reg, reg optimisation */
1896
                    gen_op_movl_T0_0();
1897
                    s->cc_op = CC_OP_LOGICB + ot;
1898
                    gen_op_mov_reg_T0[ot][reg]();
1899
                    gen_op_update1_cc();
1900
                    break;
1901
                } else {
1902
                    opreg = rm;
1903
                }
1904
                gen_op_mov_TN_reg[ot][1][reg]();
1905
                gen_op(s, op, ot, opreg);
1906
                break;
1907
            case 1: /* OP Gv, Ev */
1908
                modrm = ldub_code(s->pc++);
1909
                mod = (modrm >> 6) & 3;
1910
                reg = ((modrm >> 3) & 7);
1911
                rm = modrm & 7;
1912
                if (mod != 3) {
1913
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1914
                    gen_op_ld_T1_A0[ot + s->mem_index]();
1915
                } else if (op == OP_XORL && rm == reg) {
1916
                    goto xor_zero;
1917
                } else {
1918
                    gen_op_mov_TN_reg[ot][1][rm]();
1919
                }
1920
                gen_op(s, op, ot, reg);
1921
                break;
1922
            case 2: /* OP A, Iv */
1923
                val = insn_get(s, ot);
1924
                gen_op_movl_T1_im(val);
1925
                gen_op(s, op, ot, OR_EAX);
1926
                break;
1927
            }
1928
        }
1929
        break;
1930

    
1931
    case 0x80: /* GRP1 */
1932
    case 0x81:
1933
    case 0x82:
1934
    case 0x83:
1935
        {
1936
            int val;
1937

    
1938
            if ((b & 1) == 0)
1939
                ot = OT_BYTE;
1940
            else
1941
                ot = dflag ? OT_LONG : OT_WORD;
1942
            
1943
            modrm = ldub_code(s->pc++);
1944
            mod = (modrm >> 6) & 3;
1945
            rm = modrm & 7;
1946
            op = (modrm >> 3) & 7;
1947
            
1948
            if (mod != 3) {
1949
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1950
                opreg = OR_TMP0;
1951
            } else {
1952
                opreg = rm + OR_EAX;
1953
            }
1954

    
1955
            switch(b) {
1956
            default:
1957
            case 0x80:
1958
            case 0x81:
1959
            case 0x82:
1960
                val = insn_get(s, ot);
1961
                break;
1962
            case 0x83:
1963
                val = (int8_t)insn_get(s, OT_BYTE);
1964
                break;
1965
            }
1966
            gen_op_movl_T1_im(val);
1967
            gen_op(s, op, ot, opreg);
1968
        }
1969
        break;
1970

    
1971
        /**************************/
1972
        /* inc, dec, and other misc arith */
1973
    case 0x40 ... 0x47: /* inc Gv */
1974
        ot = dflag ? OT_LONG : OT_WORD;
1975
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1976
        break;
1977
    case 0x48 ... 0x4f: /* dec Gv */
1978
        ot = dflag ? OT_LONG : OT_WORD;
1979
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1980
        break;
1981
    case 0xf6: /* GRP3 */
1982
    case 0xf7:
1983
        if ((b & 1) == 0)
1984
            ot = OT_BYTE;
1985
        else
1986
            ot = dflag ? OT_LONG : OT_WORD;
1987

    
1988
        modrm = ldub_code(s->pc++);
1989
        mod = (modrm >> 6) & 3;
1990
        rm = modrm & 7;
1991
        op = (modrm >> 3) & 7;
1992
        if (mod != 3) {
1993
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1994
            gen_op_ld_T0_A0[ot + s->mem_index]();
1995
        } else {
1996
            gen_op_mov_TN_reg[ot][0][rm]();
1997
        }
1998

    
1999
        switch(op) {
2000
        case 0: /* test */
2001
            val = insn_get(s, ot);
2002
            gen_op_movl_T1_im(val);
2003
            gen_op_testl_T0_T1_cc();
2004
            s->cc_op = CC_OP_LOGICB + ot;
2005
            break;
2006
        case 2: /* not */
2007
            gen_op_notl_T0();
2008
            if (mod != 3) {
2009
                gen_op_st_T0_A0[ot + s->mem_index]();
2010
            } else {
2011
                gen_op_mov_reg_T0[ot][rm]();
2012
            }
2013
            break;
2014
        case 3: /* neg */
2015
            gen_op_negl_T0();
2016
            if (mod != 3) {
2017
                gen_op_st_T0_A0[ot + s->mem_index]();
2018
            } else {
2019
                gen_op_mov_reg_T0[ot][rm]();
2020
            }
2021
            gen_op_update_neg_cc();
2022
            s->cc_op = CC_OP_SUBB + ot;
2023
            break;
2024
        case 4: /* mul */
2025
            switch(ot) {
2026
            case OT_BYTE:
2027
                gen_op_mulb_AL_T0();
2028
                s->cc_op = CC_OP_MULB;
2029
                break;
2030
            case OT_WORD:
2031
                gen_op_mulw_AX_T0();
2032
                s->cc_op = CC_OP_MULW;
2033
                break;
2034
            default:
2035
            case OT_LONG:
2036
                gen_op_mull_EAX_T0();
2037
                s->cc_op = CC_OP_MULL;
2038
                break;
2039
            }
2040
            break;
2041
        case 5: /* imul */
2042
            switch(ot) {
2043
            case OT_BYTE:
2044
                gen_op_imulb_AL_T0();
2045
                s->cc_op = CC_OP_MULB;
2046
                break;
2047
            case OT_WORD:
2048
                gen_op_imulw_AX_T0();
2049
                s->cc_op = CC_OP_MULW;
2050
                break;
2051
            default:
2052
            case OT_LONG:
2053
                gen_op_imull_EAX_T0();
2054
                s->cc_op = CC_OP_MULL;
2055
                break;
2056
            }
2057
            break;
2058
        case 6: /* div */
2059
            switch(ot) {
2060
            case OT_BYTE:
2061
                gen_op_divb_AL_T0(pc_start - s->cs_base);
2062
                break;
2063
            case OT_WORD:
2064
                gen_op_divw_AX_T0(pc_start - s->cs_base);
2065
                break;
2066
            default:
2067
            case OT_LONG:
2068
                gen_op_divl_EAX_T0(pc_start - s->cs_base);
2069
                break;
2070
            }
2071
            break;
2072
        case 7: /* idiv */
2073
            switch(ot) {
2074
            case OT_BYTE:
2075
                gen_op_idivb_AL_T0(pc_start - s->cs_base);
2076
                break;
2077
            case OT_WORD:
2078
                gen_op_idivw_AX_T0(pc_start - s->cs_base);
2079
                break;
2080
            default:
2081
            case OT_LONG:
2082
                gen_op_idivl_EAX_T0(pc_start - s->cs_base);
2083
                break;
2084
            }
2085
            break;
2086
        default:
2087
            goto illegal_op;
2088
        }
2089
        break;
2090

    
2091
    case 0xfe: /* GRP4 */
2092
    case 0xff: /* GRP5 */
2093
        if ((b & 1) == 0)
2094
            ot = OT_BYTE;
2095
        else
2096
            ot = dflag ? OT_LONG : OT_WORD;
2097

    
2098
        modrm = ldub_code(s->pc++);
2099
        mod = (modrm >> 6) & 3;
2100
        rm = modrm & 7;
2101
        op = (modrm >> 3) & 7;
2102
        if (op >= 2 && b == 0xfe) {
2103
            goto illegal_op;
2104
        }
2105
        if (mod != 3) {
2106
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2107
            if (op >= 2 && op != 3 && op != 5)
2108
                gen_op_ld_T0_A0[ot + s->mem_index]();
2109
        } else {
2110
            gen_op_mov_TN_reg[ot][0][rm]();
2111
        }
2112

    
2113
        switch(op) {
2114
        case 0: /* inc Ev */
2115
            if (mod != 3)
2116
                opreg = OR_TMP0;
2117
            else
2118
                opreg = rm;
2119
            gen_inc(s, ot, opreg, 1);
2120
            break;
2121
        case 1: /* dec Ev */
2122
            if (mod != 3)
2123
                opreg = OR_TMP0;
2124
            else
2125
                opreg = rm;
2126
            gen_inc(s, ot, opreg, -1);
2127
            break;
2128
        case 2: /* call Ev */
2129
            /* XXX: optimize if memory (no 'and' is necessary) */
2130
            if (s->dflag == 0)
2131
                gen_op_andl_T0_ffff();
2132
            next_eip = s->pc - s->cs_base;
2133
            gen_op_movl_T1_im(next_eip);
2134
            gen_push_T1(s);
2135
            gen_op_jmp_T0();
2136
            gen_eob(s);
2137
            break;
2138
        case 3: /* lcall Ev */
2139
            gen_op_ld_T1_A0[ot + s->mem_index]();
2140
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2141
            gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2142
        do_lcall:
2143
            if (s->pe && !s->vm86) {
2144
                if (s->cc_op != CC_OP_DYNAMIC)
2145
                    gen_op_set_cc_op(s->cc_op);
2146
                gen_op_jmp_im(pc_start - s->cs_base);
2147
                gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
2148
            } else {
2149
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2150
            }
2151
            gen_eob(s);
2152
            break;
2153
        case 4: /* jmp Ev */
2154
            if (s->dflag == 0)
2155
                gen_op_andl_T0_ffff();
2156
            gen_op_jmp_T0();
2157
            gen_eob(s);
2158
            break;
2159
        case 5: /* ljmp Ev */
2160
            gen_op_ld_T1_A0[ot + s->mem_index]();
2161
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2162
            gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2163
        do_ljmp:
2164
            if (s->pe && !s->vm86) {
2165
                if (s->cc_op != CC_OP_DYNAMIC)
2166
                    gen_op_set_cc_op(s->cc_op);
2167
                gen_op_jmp_im(pc_start - s->cs_base);
2168
                gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base);
2169
            } else {
2170
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
2171
                gen_op_movl_T0_T1();
2172
                gen_op_jmp_T0();
2173
            }
2174
            gen_eob(s);
2175
            break;
2176
        case 6: /* push Ev */
2177
            gen_push_T0(s);
2178
            break;
2179
        default:
2180
            goto illegal_op;
2181
        }
2182
        break;
2183

    
2184
    case 0x84: /* test Ev, Gv */
2185
    case 0x85: 
2186
        if ((b & 1) == 0)
2187
            ot = OT_BYTE;
2188
        else
2189
            ot = dflag ? OT_LONG : OT_WORD;
2190

    
2191
        modrm = ldub_code(s->pc++);
2192
        mod = (modrm >> 6) & 3;
2193
        rm = modrm & 7;
2194
        reg = (modrm >> 3) & 7;
2195
        
2196
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2197
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
2198
        gen_op_testl_T0_T1_cc();
2199
        s->cc_op = CC_OP_LOGICB + ot;
2200
        break;
2201
        
2202
    case 0xa8: /* test eAX, Iv */
2203
    case 0xa9:
2204
        if ((b & 1) == 0)
2205
            ot = OT_BYTE;
2206
        else
2207
            ot = dflag ? OT_LONG : OT_WORD;
2208
        val = insn_get(s, ot);
2209

    
2210
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
2211
        gen_op_movl_T1_im(val);
2212
        gen_op_testl_T0_T1_cc();
2213
        s->cc_op = CC_OP_LOGICB + ot;
2214
        break;
2215
        
2216
    case 0x98: /* CWDE/CBW */
2217
        if (dflag)
2218
            gen_op_movswl_EAX_AX();
2219
        else
2220
            gen_op_movsbw_AX_AL();
2221
        break;
2222
    case 0x99: /* CDQ/CWD */
2223
        if (dflag)
2224
            gen_op_movslq_EDX_EAX();
2225
        else
2226
            gen_op_movswl_DX_AX();
2227
        break;
2228
    case 0x1af: /* imul Gv, Ev */
2229
    case 0x69: /* imul Gv, Ev, I */
2230
    case 0x6b:
2231
        ot = dflag ? OT_LONG : OT_WORD;
2232
        modrm = ldub_code(s->pc++);
2233
        reg = ((modrm >> 3) & 7) + OR_EAX;
2234
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2235
        if (b == 0x69) {
2236
            val = insn_get(s, ot);
2237
            gen_op_movl_T1_im(val);
2238
        } else if (b == 0x6b) {
2239
            val = (int8_t)insn_get(s, OT_BYTE);
2240
            gen_op_movl_T1_im(val);
2241
        } else {
2242
            gen_op_mov_TN_reg[ot][1][reg]();
2243
        }
2244

    
2245
        if (ot == OT_LONG) {
2246
            gen_op_imull_T0_T1();
2247
        } else {
2248
            gen_op_imulw_T0_T1();
2249
        }
2250
        gen_op_mov_reg_T0[ot][reg]();
2251
        s->cc_op = CC_OP_MULB + ot;
2252
        break;
2253
    case 0x1c0:
2254
    case 0x1c1: /* xadd Ev, Gv */
2255
        if ((b & 1) == 0)
2256
            ot = OT_BYTE;
2257
        else
2258
            ot = dflag ? OT_LONG : OT_WORD;
2259
        modrm = ldub_code(s->pc++);
2260
        reg = (modrm >> 3) & 7;
2261
        mod = (modrm >> 6) & 3;
2262
        if (mod == 3) {
2263
            rm = modrm & 7;
2264
            gen_op_mov_TN_reg[ot][0][reg]();
2265
            gen_op_mov_TN_reg[ot][1][rm]();
2266
            gen_op_addl_T0_T1();
2267
            gen_op_mov_reg_T1[ot][reg]();
2268
            gen_op_mov_reg_T0[ot][rm]();
2269
        } else {
2270
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2271
            gen_op_mov_TN_reg[ot][0][reg]();
2272
            gen_op_ld_T1_A0[ot + s->mem_index]();
2273
            gen_op_addl_T0_T1();
2274
            gen_op_st_T0_A0[ot + s->mem_index]();
2275
            gen_op_mov_reg_T1[ot][reg]();
2276
        }
2277
        gen_op_update2_cc();
2278
        s->cc_op = CC_OP_ADDB + ot;
2279
        break;
2280
    case 0x1b0:
2281
    case 0x1b1: /* cmpxchg Ev, Gv */
2282
        if ((b & 1) == 0)
2283
            ot = OT_BYTE;
2284
        else
2285
            ot = dflag ? OT_LONG : OT_WORD;
2286
        modrm = ldub_code(s->pc++);
2287
        reg = (modrm >> 3) & 7;
2288
        mod = (modrm >> 6) & 3;
2289
        gen_op_mov_TN_reg[ot][1][reg]();
2290
        if (mod == 3) {
2291
            rm = modrm & 7;
2292
            gen_op_mov_TN_reg[ot][0][rm]();
2293
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
2294
            gen_op_mov_reg_T0[ot][rm]();
2295
        } else {
2296
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2297
            gen_op_ld_T0_A0[ot + s->mem_index]();
2298
            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
2299
        }
2300
        s->cc_op = CC_OP_SUBB + ot;
2301
        break;
2302
    case 0x1c7: /* cmpxchg8b */
2303
        modrm = ldub_code(s->pc++);
2304
        mod = (modrm >> 6) & 3;
2305
        if (mod == 3)
2306
            goto illegal_op;
2307
        if (s->cc_op != CC_OP_DYNAMIC)
2308
            gen_op_set_cc_op(s->cc_op);
2309
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2310
        gen_op_cmpxchg8b();
2311
        s->cc_op = CC_OP_EFLAGS;
2312
        break;
2313
        
2314
        /**************************/
2315
        /* push/pop */
2316
    case 0x50 ... 0x57: /* push */
2317
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2318
        gen_push_T0(s);
2319
        break;
2320
    case 0x58 ... 0x5f: /* pop */
2321
        ot = dflag ? OT_LONG : OT_WORD;
2322
        gen_pop_T0(s);
2323
        /* NOTE: order is important for pop %sp */
2324
        gen_pop_update(s);
2325
        gen_op_mov_reg_T0[ot][b & 7]();
2326
        break;
2327
    case 0x60: /* pusha */
2328
        gen_pusha(s);
2329
        break;
2330
    case 0x61: /* popa */
2331
        gen_popa(s);
2332
        break;
2333
    case 0x68: /* push Iv */
2334
    case 0x6a:
2335
        ot = dflag ? OT_LONG : OT_WORD;
2336
        if (b == 0x68)
2337
            val = insn_get(s, ot);
2338
        else
2339
            val = (int8_t)insn_get(s, OT_BYTE);
2340
        gen_op_movl_T0_im(val);
2341
        gen_push_T0(s);
2342
        break;
2343
    case 0x8f: /* pop Ev */
2344
        ot = dflag ? OT_LONG : OT_WORD;
2345
        modrm = ldub_code(s->pc++);
2346
        mod = (modrm >> 6) & 3;
2347
        gen_pop_T0(s);
2348
        if (mod == 3) {
2349
            /* NOTE: order is important for pop %sp */
2350
            gen_pop_update(s);
2351
            rm = modrm & 7;
2352
            gen_op_mov_reg_T0[ot][rm]();
2353
        } else {
2354
            /* NOTE: order is important too for MMU exceptions */
2355
            s->popl_esp_hack = 2 << dflag;
2356
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2357
            s->popl_esp_hack = 0;
2358
            gen_pop_update(s);
2359
        }
2360
        break;
2361
    case 0xc8: /* enter */
2362
        {
2363
            int level;
2364
            val = lduw_code(s->pc);
2365
            s->pc += 2;
2366
            level = ldub_code(s->pc++);
2367
            gen_enter(s, val, level);
2368
        }
2369
        break;
2370
    case 0xc9: /* leave */
2371
        /* XXX: exception not precise (ESP is updated before potential exception) */
2372
        if (s->ss32) {
2373
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2374
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2375
        } else {
2376
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2377
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2378
        }
2379
        gen_pop_T0(s);
2380
        ot = dflag ? OT_LONG : OT_WORD;
2381
        gen_op_mov_reg_T0[ot][R_EBP]();
2382
        gen_pop_update(s);
2383
        break;
2384
    case 0x06: /* push es */
2385
    case 0x0e: /* push cs */
2386
    case 0x16: /* push ss */
2387
    case 0x1e: /* push ds */
2388
        gen_op_movl_T0_seg(b >> 3);
2389
        gen_push_T0(s);
2390
        break;
2391
    case 0x1a0: /* push fs */
2392
    case 0x1a8: /* push gs */
2393
        gen_op_movl_T0_seg((b >> 3) & 7);
2394
        gen_push_T0(s);
2395
        break;
2396
    case 0x07: /* pop es */
2397
    case 0x17: /* pop ss */
2398
    case 0x1f: /* pop ds */
2399
        reg = b >> 3;
2400
        gen_pop_T0(s);
2401
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2402
        gen_pop_update(s);
2403
        if (reg == R_SS) {
2404
            /* if reg == SS, inhibit interrupts/trace. */
2405
            /* If several instructions disable interrupts, only the
2406
               _first_ does it */
2407
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2408
                gen_op_set_inhibit_irq();
2409
            s->tf = 0;
2410
        }
2411
        if (s->is_jmp) {
2412
            gen_op_jmp_im(s->pc - s->cs_base);
2413
            gen_eob(s);
2414
        }
2415
        break;
2416
    case 0x1a1: /* pop fs */
2417
    case 0x1a9: /* pop gs */
2418
        gen_pop_T0(s);
2419
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2420
        gen_pop_update(s);
2421
        if (s->is_jmp) {
2422
            gen_op_jmp_im(s->pc - s->cs_base);
2423
            gen_eob(s);
2424
        }
2425
        break;
2426

    
2427
        /**************************/
2428
        /* mov */
2429
    case 0x88:
2430
    case 0x89: /* mov Gv, Ev */
2431
        if ((b & 1) == 0)
2432
            ot = OT_BYTE;
2433
        else
2434
            ot = dflag ? OT_LONG : OT_WORD;
2435
        modrm = ldub_code(s->pc++);
2436
        reg = (modrm >> 3) & 7;
2437
        
2438
        /* generate a generic store */
2439
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2440
        break;
2441
    case 0xc6:
2442
    case 0xc7: /* mov Ev, Iv */
2443
        if ((b & 1) == 0)
2444
            ot = OT_BYTE;
2445
        else
2446
            ot = dflag ? OT_LONG : OT_WORD;
2447
        modrm = ldub_code(s->pc++);
2448
        mod = (modrm >> 6) & 3;
2449
        if (mod != 3)
2450
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2451
        val = insn_get(s, ot);
2452
        gen_op_movl_T0_im(val);
2453
        if (mod != 3)
2454
            gen_op_st_T0_A0[ot + s->mem_index]();
2455
        else
2456
            gen_op_mov_reg_T0[ot][modrm & 7]();
2457
        break;
2458
    case 0x8a:
2459
    case 0x8b: /* mov Ev, Gv */
2460
        if ((b & 1) == 0)
2461
            ot = OT_BYTE;
2462
        else
2463
            ot = dflag ? OT_LONG : OT_WORD;
2464
        modrm = ldub_code(s->pc++);
2465
        reg = (modrm >> 3) & 7;
2466
        
2467
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2468
        gen_op_mov_reg_T0[ot][reg]();
2469
        break;
2470
    case 0x8e: /* mov seg, Gv */
2471
        modrm = ldub_code(s->pc++);
2472
        reg = (modrm >> 3) & 7;
2473
        if (reg >= 6 || reg == R_CS)
2474
            goto illegal_op;
2475
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2476
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2477
        if (reg == R_SS) {
2478
            /* if reg == SS, inhibit interrupts/trace */
2479
            /* If several instructions disable interrupts, only the
2480
               _first_ does it */
2481
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2482
                gen_op_set_inhibit_irq();
2483
            s->tf = 0;
2484
        }
2485
        if (s->is_jmp) {
2486
            gen_op_jmp_im(s->pc - s->cs_base);
2487
            gen_eob(s);
2488
        }
2489
        break;
2490
    case 0x8c: /* mov Gv, seg */
2491
        modrm = ldub_code(s->pc++);
2492
        reg = (modrm >> 3) & 7;
2493
        mod = (modrm >> 6) & 3;
2494
        if (reg >= 6)
2495
            goto illegal_op;
2496
        gen_op_movl_T0_seg(reg);
2497
        ot = OT_WORD;
2498
        if (mod == 3 && dflag)
2499
            ot = OT_LONG;
2500
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2501
        break;
2502

    
2503
    case 0x1b6: /* movzbS Gv, Eb */
2504
    case 0x1b7: /* movzwS Gv, Eb */
2505
    case 0x1be: /* movsbS Gv, Eb */
2506
    case 0x1bf: /* movswS Gv, Eb */
2507
        {
2508
            int d_ot;
2509
            /* d_ot is the size of destination */
2510
            d_ot = dflag + OT_WORD;
2511
            /* ot is the size of source */
2512
            ot = (b & 1) + OT_BYTE;
2513
            modrm = ldub_code(s->pc++);
2514
            reg = ((modrm >> 3) & 7) + OR_EAX;
2515
            mod = (modrm >> 6) & 3;
2516
            rm = modrm & 7;
2517
            
2518
            if (mod == 3) {
2519
                gen_op_mov_TN_reg[ot][0][rm]();
2520
                switch(ot | (b & 8)) {
2521
                case OT_BYTE:
2522
                    gen_op_movzbl_T0_T0();
2523
                    break;
2524
                case OT_BYTE | 8:
2525
                    gen_op_movsbl_T0_T0();
2526
                    break;
2527
                case OT_WORD:
2528
                    gen_op_movzwl_T0_T0();
2529
                    break;
2530
                default:
2531
                case OT_WORD | 8:
2532
                    gen_op_movswl_T0_T0();
2533
                    break;
2534
                }
2535
                gen_op_mov_reg_T0[d_ot][reg]();
2536
            } else {
2537
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2538
                if (b & 8) {
2539
                    gen_op_lds_T0_A0[ot + s->mem_index]();
2540
                } else {
2541
                    gen_op_ldu_T0_A0[ot + s->mem_index]();
2542
                }
2543
                gen_op_mov_reg_T0[d_ot][reg]();
2544
            }
2545
        }
2546
        break;
2547

    
2548
    case 0x8d: /* lea */
2549
        ot = dflag ? OT_LONG : OT_WORD;
2550
        modrm = ldub_code(s->pc++);
2551
        mod = (modrm >> 6) & 3;
2552
        if (mod == 3)
2553
            goto illegal_op;
2554
        reg = (modrm >> 3) & 7;
2555
        /* we must ensure that no segment is added */
2556
        s->override = -1;
2557
        val = s->addseg;
2558
        s->addseg = 0;
2559
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2560
        s->addseg = val;
2561
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2562
        break;
2563
        
2564
    case 0xa0: /* mov EAX, Ov */
2565
    case 0xa1:
2566
    case 0xa2: /* mov Ov, EAX */
2567
    case 0xa3:
2568
        if ((b & 1) == 0)
2569
            ot = OT_BYTE;
2570
        else
2571
            ot = dflag ? OT_LONG : OT_WORD;
2572
        if (s->aflag)
2573
            offset_addr = insn_get(s, OT_LONG);
2574
        else
2575
            offset_addr = insn_get(s, OT_WORD);
2576
        gen_op_movl_A0_im(offset_addr);
2577
        /* handle override */
2578
        {
2579
            int override, must_add_seg;
2580
            must_add_seg = s->addseg;
2581
            if (s->override >= 0) {
2582
                override = s->override;
2583
                must_add_seg = 1;
2584
            } else {
2585
                override = R_DS;
2586
            }
2587
            if (must_add_seg) {
2588
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2589
            }
2590
        }
2591
        if ((b & 2) == 0) {
2592
            gen_op_ld_T0_A0[ot + s->mem_index]();
2593
            gen_op_mov_reg_T0[ot][R_EAX]();
2594
        } else {
2595
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2596
            gen_op_st_T0_A0[ot + s->mem_index]();
2597
        }
2598
        break;
2599
    case 0xd7: /* xlat */
2600
        gen_op_movl_A0_reg[R_EBX]();
2601
        gen_op_addl_A0_AL();
2602
        if (s->aflag == 0)
2603
            gen_op_andl_A0_ffff();
2604
        /* handle override */
2605
        {
2606
            int override, must_add_seg;
2607
            must_add_seg = s->addseg;
2608
            override = R_DS;
2609
            if (s->override >= 0) {
2610
                override = s->override;
2611
                must_add_seg = 1;
2612
            } else {
2613
                override = R_DS;
2614
            }
2615
            if (must_add_seg) {
2616
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2617
            }
2618
        }
2619
        gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
2620
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2621
        break;
2622
    case 0xb0 ... 0xb7: /* mov R, Ib */
2623
        val = insn_get(s, OT_BYTE);
2624
        gen_op_movl_T0_im(val);
2625
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2626
        break;
2627
    case 0xb8 ... 0xbf: /* mov R, Iv */
2628
        ot = dflag ? OT_LONG : OT_WORD;
2629
        val = insn_get(s, ot);
2630
        reg = OR_EAX + (b & 7);
2631
        gen_op_movl_T0_im(val);
2632
        gen_op_mov_reg_T0[ot][reg]();
2633
        break;
2634

    
2635
    case 0x91 ... 0x97: /* xchg R, EAX */
2636
        ot = dflag ? OT_LONG : OT_WORD;
2637
        reg = b & 7;
2638
        rm = R_EAX;
2639
        goto do_xchg_reg;
2640
    case 0x86:
2641
    case 0x87: /* xchg Ev, Gv */
2642
        if ((b & 1) == 0)
2643
            ot = OT_BYTE;
2644
        else
2645
            ot = dflag ? OT_LONG : OT_WORD;
2646
        modrm = ldub_code(s->pc++);
2647
        reg = (modrm >> 3) & 7;
2648
        mod = (modrm >> 6) & 3;
2649
        if (mod == 3) {
2650
            rm = modrm & 7;
2651
        do_xchg_reg:
2652
            gen_op_mov_TN_reg[ot][0][reg]();
2653
            gen_op_mov_TN_reg[ot][1][rm]();
2654
            gen_op_mov_reg_T0[ot][rm]();
2655
            gen_op_mov_reg_T1[ot][reg]();
2656
        } else {
2657
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2658
            gen_op_mov_TN_reg[ot][0][reg]();
2659
            /* for xchg, lock is implicit */
2660
            if (!(prefixes & PREFIX_LOCK))
2661
                gen_op_lock();
2662
            gen_op_ld_T1_A0[ot + s->mem_index]();
2663
            gen_op_st_T0_A0[ot + s->mem_index]();
2664
            if (!(prefixes & PREFIX_LOCK))
2665
                gen_op_unlock();
2666
            gen_op_mov_reg_T1[ot][reg]();
2667
        }
2668
        break;
2669
    case 0xc4: /* les Gv */
2670
        op = R_ES;
2671
        goto do_lxx;
2672
    case 0xc5: /* lds Gv */
2673
        op = R_DS;
2674
        goto do_lxx;
2675
    case 0x1b2: /* lss Gv */
2676
        op = R_SS;
2677
        goto do_lxx;
2678
    case 0x1b4: /* lfs Gv */
2679
        op = R_FS;
2680
        goto do_lxx;
2681
    case 0x1b5: /* lgs Gv */
2682
        op = R_GS;
2683
    do_lxx:
2684
        ot = dflag ? OT_LONG : OT_WORD;
2685
        modrm = ldub_code(s->pc++);
2686
        reg = (modrm >> 3) & 7;
2687
        mod = (modrm >> 6) & 3;
2688
        if (mod == 3)
2689
            goto illegal_op;
2690
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2691
        gen_op_ld_T1_A0[ot + s->mem_index]();
2692
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2693
        /* load the segment first to handle exceptions properly */
2694
        gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2695
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2696
        /* then put the data */
2697
        gen_op_mov_reg_T1[ot][reg]();
2698
        if (s->is_jmp) {
2699
            gen_op_jmp_im(s->pc - s->cs_base);
2700
            gen_eob(s);
2701
        }
2702
        break;
2703
        
2704
        /************************/
2705
        /* shifts */
2706
    case 0xc0:
2707
    case 0xc1:
2708
        /* shift Ev,Ib */
2709
        shift = 2;
2710
    grp2:
2711
        {
2712
            if ((b & 1) == 0)
2713
                ot = OT_BYTE;
2714
            else
2715
                ot = dflag ? OT_LONG : OT_WORD;
2716
            
2717
            modrm = ldub_code(s->pc++);
2718
            mod = (modrm >> 6) & 3;
2719
            rm = modrm & 7;
2720
            op = (modrm >> 3) & 7;
2721
            
2722
            if (mod != 3) {
2723
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2724
                opreg = OR_TMP0;
2725
            } else {
2726
                opreg = rm + OR_EAX;
2727
            }
2728

    
2729
            /* simpler op */
2730
            if (shift == 0) {
2731
                gen_shift(s, op, ot, opreg, OR_ECX);
2732
            } else {
2733
                if (shift == 2) {
2734
                    shift = ldub_code(s->pc++);
2735
                }
2736
                gen_shifti(s, op, ot, opreg, shift);
2737
            }
2738
        }
2739
        break;
2740
    case 0xd0:
2741
    case 0xd1:
2742
        /* shift Ev,1 */
2743
        shift = 1;
2744
        goto grp2;
2745
    case 0xd2:
2746
    case 0xd3:
2747
        /* shift Ev,cl */
2748
        shift = 0;
2749
        goto grp2;
2750

    
2751
    case 0x1a4: /* shld imm */
2752
        op = 0;
2753
        shift = 1;
2754
        goto do_shiftd;
2755
    case 0x1a5: /* shld cl */
2756
        op = 0;
2757
        shift = 0;
2758
        goto do_shiftd;
2759
    case 0x1ac: /* shrd imm */
2760
        op = 1;
2761
        shift = 1;
2762
        goto do_shiftd;
2763
    case 0x1ad: /* shrd cl */
2764
        op = 1;
2765
        shift = 0;
2766
    do_shiftd:
2767
        ot = dflag ? OT_LONG : OT_WORD;
2768
        modrm = ldub_code(s->pc++);
2769
        mod = (modrm >> 6) & 3;
2770
        rm = modrm & 7;
2771
        reg = (modrm >> 3) & 7;
2772
        
2773
        if (mod != 3) {
2774
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2775
            gen_op_ld_T0_A0[ot + s->mem_index]();
2776
        } else {
2777
            gen_op_mov_TN_reg[ot][0][rm]();
2778
        }
2779
        gen_op_mov_TN_reg[ot][1][reg]();
2780
        
2781
        if (shift) {
2782
            val = ldub_code(s->pc++);
2783
            val &= 0x1f;
2784
            if (val) {
2785
                if (mod == 3)
2786
                    gen_op_shiftd_T0_T1_im_cc[ot][op](val);
2787
                else
2788
                    gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
2789
                if (op == 0 && ot != OT_WORD)
2790
                    s->cc_op = CC_OP_SHLB + ot;
2791
                else
2792
                    s->cc_op = CC_OP_SARB + ot;
2793
            }
2794
        } else {
2795
            if (s->cc_op != CC_OP_DYNAMIC)
2796
                gen_op_set_cc_op(s->cc_op);
2797
            if (mod == 3)
2798
                gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
2799
            else
2800
                gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
2801
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2802
        }
2803
        if (mod == 3) {
2804
            gen_op_mov_reg_T0[ot][rm]();
2805
        }
2806
        break;
2807

    
2808
        /************************/
2809
        /* floats */
2810
    case 0xd8 ... 0xdf: 
2811
        if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
2812
            /* if CR0.EM or CR0.TS are set, generate an FPU exception */
2813
            /* XXX: what to do if illegal op ? */
2814
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2815
            break;
2816
        }
2817
        modrm = ldub_code(s->pc++);
2818
        mod = (modrm >> 6) & 3;
2819
        rm = modrm & 7;
2820
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2821
        if (mod != 3) {
2822
            /* memory op */
2823
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2824
            switch(op) {
2825
            case 0x00 ... 0x07: /* fxxxs */
2826
            case 0x10 ... 0x17: /* fixxxl */
2827
            case 0x20 ... 0x27: /* fxxxl */
2828
            case 0x30 ... 0x37: /* fixxx */
2829
                {
2830
                    int op1;
2831
                    op1 = op & 7;
2832

    
2833
                    switch(op >> 4) {
2834
                    case 0:
2835
                        gen_op_flds_FT0_A0();
2836
                        break;
2837
                    case 1:
2838
                        gen_op_fildl_FT0_A0();
2839
                        break;
2840
                    case 2:
2841
                        gen_op_fldl_FT0_A0();
2842
                        break;
2843
                    case 3:
2844
                    default:
2845
                        gen_op_fild_FT0_A0();
2846
                        break;
2847
                    }
2848
                    
2849
                    gen_op_fp_arith_ST0_FT0[op1]();
2850
                    if (op1 == 3) {
2851
                        /* fcomp needs pop */
2852
                        gen_op_fpop();
2853
                    }
2854
                }
2855
                break;
2856
            case 0x08: /* flds */
2857
            case 0x0a: /* fsts */
2858
            case 0x0b: /* fstps */
2859
            case 0x18: /* fildl */
2860
            case 0x1a: /* fistl */
2861
            case 0x1b: /* fistpl */
2862
            case 0x28: /* fldl */
2863
            case 0x2a: /* fstl */
2864
            case 0x2b: /* fstpl */
2865
            case 0x38: /* filds */
2866
            case 0x3a: /* fists */
2867
            case 0x3b: /* fistps */
2868
                
2869
                switch(op & 7) {
2870
                case 0:
2871
                    switch(op >> 4) {
2872
                    case 0:
2873
                        gen_op_flds_ST0_A0();
2874
                        break;
2875
                    case 1:
2876
                        gen_op_fildl_ST0_A0();
2877
                        break;
2878
                    case 2:
2879
                        gen_op_fldl_ST0_A0();
2880
                        break;
2881
                    case 3:
2882
                    default:
2883
                        gen_op_fild_ST0_A0();
2884
                        break;
2885
                    }
2886
                    break;
2887
                default:
2888
                    switch(op >> 4) {
2889
                    case 0:
2890
                        gen_op_fsts_ST0_A0();
2891
                        break;
2892
                    case 1:
2893
                        gen_op_fistl_ST0_A0();
2894
                        break;
2895
                    case 2:
2896
                        gen_op_fstl_ST0_A0();
2897
                        break;
2898
                    case 3:
2899
                    default:
2900
                        gen_op_fist_ST0_A0();
2901
                        break;
2902
                    }
2903
                    if ((op & 7) == 3)
2904
                        gen_op_fpop();
2905
                    break;
2906
                }
2907
                break;
2908
            case 0x0c: /* fldenv mem */
2909
                gen_op_fldenv_A0(s->dflag);
2910
                break;
2911
            case 0x0d: /* fldcw mem */
2912
                gen_op_fldcw_A0();
2913
                break;
2914
            case 0x0e: /* fnstenv mem */
2915
                gen_op_fnstenv_A0(s->dflag);
2916
                break;
2917
            case 0x0f: /* fnstcw mem */
2918
                gen_op_fnstcw_A0();
2919
                break;
2920
            case 0x1d: /* fldt mem */
2921
                gen_op_fldt_ST0_A0();
2922
                break;
2923
            case 0x1f: /* fstpt mem */
2924
                gen_op_fstt_ST0_A0();
2925
                gen_op_fpop();
2926
                break;
2927
            case 0x2c: /* frstor mem */
2928
                gen_op_frstor_A0(s->dflag);
2929
                break;
2930
            case 0x2e: /* fnsave mem */
2931
                gen_op_fnsave_A0(s->dflag);
2932
                break;
2933
            case 0x2f: /* fnstsw mem */
2934
                gen_op_fnstsw_A0();
2935
                break;
2936
            case 0x3c: /* fbld */
2937
                gen_op_fbld_ST0_A0();
2938
                break;
2939
            case 0x3e: /* fbstp */
2940
                gen_op_fbst_ST0_A0();
2941
                gen_op_fpop();
2942
                break;
2943
            case 0x3d: /* fildll */
2944
                gen_op_fildll_ST0_A0();
2945
                break;
2946
            case 0x3f: /* fistpll */
2947
                gen_op_fistll_ST0_A0();
2948
                gen_op_fpop();
2949
                break;
2950
            default:
2951
                goto illegal_op;
2952
            }
2953
        } else {
2954
            /* register float ops */
2955
            opreg = rm;
2956

    
2957
            switch(op) {
2958
            case 0x08: /* fld sti */
2959
                gen_op_fpush();
2960
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2961
                break;
2962
            case 0x09: /* fxchg sti */
2963
            case 0x29: /* fxchg4 sti, undocumented op */
2964
            case 0x39: /* fxchg7 sti, undocumented op */
2965
                gen_op_fxchg_ST0_STN(opreg);
2966
                break;
2967
            case 0x0a: /* grp d9/2 */
2968
                switch(rm) {
2969
                case 0: /* fnop */
2970
                    /* check exceptions (FreeBSD FPU probe) */
2971
                    if (s->cc_op != CC_OP_DYNAMIC)
2972
                        gen_op_set_cc_op(s->cc_op);
2973
                    gen_op_jmp_im(pc_start - s->cs_base);
2974
                    gen_op_fwait();
2975
                    break;
2976
                default:
2977
                    goto illegal_op;
2978
                }
2979
                break;
2980
            case 0x0c: /* grp d9/4 */
2981
                switch(rm) {
2982
                case 0: /* fchs */
2983
                    gen_op_fchs_ST0();
2984
                    break;
2985
                case 1: /* fabs */
2986
                    gen_op_fabs_ST0();
2987
                    break;
2988
                case 4: /* ftst */
2989
                    gen_op_fldz_FT0();
2990
                    gen_op_fcom_ST0_FT0();
2991
                    break;
2992
                case 5: /* fxam */
2993
                    gen_op_fxam_ST0();
2994
                    break;
2995
                default:
2996
                    goto illegal_op;
2997
                }
2998
                break;
2999
            case 0x0d: /* grp d9/5 */
3000
                {
3001
                    switch(rm) {
3002
                    case 0:
3003
                        gen_op_fpush();
3004
                        gen_op_fld1_ST0();
3005
                        break;
3006
                    case 1:
3007
                        gen_op_fpush();
3008
                        gen_op_fldl2t_ST0();
3009
                        break;
3010
                    case 2:
3011
                        gen_op_fpush();
3012
                        gen_op_fldl2e_ST0();
3013
                        break;
3014
                    case 3:
3015
                        gen_op_fpush();
3016
                        gen_op_fldpi_ST0();
3017
                        break;
3018
                    case 4:
3019
                        gen_op_fpush();
3020
                        gen_op_fldlg2_ST0();
3021
                        break;
3022
                    case 5:
3023
                        gen_op_fpush();
3024
                        gen_op_fldln2_ST0();
3025
                        break;
3026
                    case 6:
3027
                        gen_op_fpush();
3028
                        gen_op_fldz_ST0();
3029
                        break;
3030
                    default:
3031
                        goto illegal_op;
3032
                    }
3033
                }
3034
                break;
3035
            case 0x0e: /* grp d9/6 */
3036
                switch(rm) {
3037
                case 0: /* f2xm1 */
3038
                    gen_op_f2xm1();
3039
                    break;
3040
                case 1: /* fyl2x */
3041
                    gen_op_fyl2x();
3042
                    break;
3043
                case 2: /* fptan */
3044
                    gen_op_fptan();
3045
                    break;
3046
                case 3: /* fpatan */
3047
                    gen_op_fpatan();
3048
                    break;
3049
                case 4: /* fxtract */
3050
                    gen_op_fxtract();
3051
                    break;
3052
                case 5: /* fprem1 */
3053
                    gen_op_fprem1();
3054
                    break;
3055
                case 6: /* fdecstp */
3056
                    gen_op_fdecstp();
3057
                    break;
3058
                default:
3059
                case 7: /* fincstp */
3060
                    gen_op_fincstp();
3061
                    break;
3062
                }
3063
                break;
3064
            case 0x0f: /* grp d9/7 */
3065
                switch(rm) {
3066
                case 0: /* fprem */
3067
                    gen_op_fprem();
3068
                    break;
3069
                case 1: /* fyl2xp1 */
3070
                    gen_op_fyl2xp1();
3071
                    break;
3072
                case 2: /* fsqrt */
3073
                    gen_op_fsqrt();
3074
                    break;
3075
                case 3: /* fsincos */
3076
                    gen_op_fsincos();
3077
                    break;
3078
                case 5: /* fscale */
3079
                    gen_op_fscale();
3080
                    break;
3081
                case 4: /* frndint */
3082
                    gen_op_frndint();
3083
                    break;
3084
                case 6: /* fsin */
3085
                    gen_op_fsin();
3086
                    break;
3087
                default:
3088
                case 7: /* fcos */
3089
                    gen_op_fcos();
3090
                    break;
3091
                }
3092
                break;
3093
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
3094
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
3095
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
3096
                {
3097
                    int op1;
3098
                    
3099
                    op1 = op & 7;
3100
                    if (op >= 0x20) {
3101
                        gen_op_fp_arith_STN_ST0[op1](opreg);
3102
                        if (op >= 0x30)
3103
                            gen_op_fpop();
3104
                    } else {
3105
                        gen_op_fmov_FT0_STN(opreg);
3106
                        gen_op_fp_arith_ST0_FT0[op1]();
3107
                    }
3108
                }
3109
                break;
3110
            case 0x02: /* fcom */
3111
            case 0x22: /* fcom2, undocumented op */
3112
                gen_op_fmov_FT0_STN(opreg);
3113
                gen_op_fcom_ST0_FT0();
3114
                break;
3115
            case 0x03: /* fcomp */
3116
            case 0x23: /* fcomp3, undocumented op */
3117
            case 0x32: /* fcomp5, undocumented op */
3118
                gen_op_fmov_FT0_STN(opreg);
3119
                gen_op_fcom_ST0_FT0();
3120
                gen_op_fpop();
3121
                break;
3122
            case 0x15: /* da/5 */
3123
                switch(rm) {
3124
                case 1: /* fucompp */
3125
                    gen_op_fmov_FT0_STN(1);
3126
                    gen_op_fucom_ST0_FT0();
3127
                    gen_op_fpop();
3128
                    gen_op_fpop();
3129
                    break;
3130
                default:
3131
                    goto illegal_op;
3132
                }
3133
                break;
3134
            case 0x1c:
3135
                switch(rm) {
3136
                case 0: /* feni (287 only, just do nop here) */
3137
                    break;
3138
                case 1: /* fdisi (287 only, just do nop here) */
3139
                    break;
3140
                case 2: /* fclex */
3141
                    gen_op_fclex();
3142
                    break;
3143
                case 3: /* fninit */
3144
                    gen_op_fninit();
3145
                    break;
3146
                case 4: /* fsetpm (287 only, just do nop here) */
3147
                    break;
3148
                default:
3149
                    goto illegal_op;
3150
                }
3151
                break;
3152
            case 0x1d: /* fucomi */
3153
                if (s->cc_op != CC_OP_DYNAMIC)
3154
                    gen_op_set_cc_op(s->cc_op);
3155
                gen_op_fmov_FT0_STN(opreg);
3156
                gen_op_fucomi_ST0_FT0();
3157
                s->cc_op = CC_OP_EFLAGS;
3158
                break;
3159
            case 0x1e: /* fcomi */
3160
                if (s->cc_op != CC_OP_DYNAMIC)
3161
                    gen_op_set_cc_op(s->cc_op);
3162
                gen_op_fmov_FT0_STN(opreg);
3163
                gen_op_fcomi_ST0_FT0();
3164
                s->cc_op = CC_OP_EFLAGS;
3165
                break;
3166
            case 0x28: /* ffree sti */
3167
                gen_op_ffree_STN(opreg);
3168
                break; 
3169
            case 0x2a: /* fst sti */
3170
                gen_op_fmov_STN_ST0(opreg);
3171
                break;
3172
            case 0x2b: /* fstp sti */
3173
            case 0x0b: /* fstp1 sti, undocumented op */
3174
            case 0x3a: /* fstp8 sti, undocumented op */
3175
            case 0x3b: /* fstp9 sti, undocumented op */
3176
                gen_op_fmov_STN_ST0(opreg);
3177
                gen_op_fpop();
3178
                break;
3179
            case 0x2c: /* fucom st(i) */
3180
                gen_op_fmov_FT0_STN(opreg);
3181
                gen_op_fucom_ST0_FT0();
3182
                break;
3183
            case 0x2d: /* fucomp st(i) */
3184
                gen_op_fmov_FT0_STN(opreg);
3185
                gen_op_fucom_ST0_FT0();
3186
                gen_op_fpop();
3187
                break;
3188
            case 0x33: /* de/3 */
3189
                switch(rm) {
3190
                case 1: /* fcompp */
3191
                    gen_op_fmov_FT0_STN(1);
3192
                    gen_op_fcom_ST0_FT0();
3193
                    gen_op_fpop();
3194
                    gen_op_fpop();
3195
                    break;
3196
                default:
3197
                    goto illegal_op;
3198
                }
3199
                break;
3200
            case 0x38: /* ffreep sti, undocumented op */
3201
                gen_op_ffree_STN(opreg);
3202
                gen_op_fpop();
3203
                break;
3204
            case 0x3c: /* df/4 */
3205
                switch(rm) {
3206
                case 0:
3207
                    gen_op_fnstsw_EAX();
3208
                    break;
3209
                default:
3210
                    goto illegal_op;
3211
                }
3212
                break;
3213
            case 0x3d: /* fucomip */
3214
                if (s->cc_op != CC_OP_DYNAMIC)
3215
                    gen_op_set_cc_op(s->cc_op);
3216
                gen_op_fmov_FT0_STN(opreg);
3217
                gen_op_fucomi_ST0_FT0();
3218
                gen_op_fpop();
3219
                s->cc_op = CC_OP_EFLAGS;
3220
                break;
3221
            case 0x3e: /* fcomip */
3222
                if (s->cc_op != CC_OP_DYNAMIC)
3223
                    gen_op_set_cc_op(s->cc_op);
3224
                gen_op_fmov_FT0_STN(opreg);
3225
                gen_op_fcomi_ST0_FT0();
3226
                gen_op_fpop();
3227
                s->cc_op = CC_OP_EFLAGS;
3228
                break;
3229
            case 0x10 ... 0x13: /* fcmovxx */
3230
            case 0x18 ... 0x1b:
3231
                {
3232
                    int op1;
3233
                    const static uint8_t fcmov_cc[8] = {
3234
                        (JCC_B << 1),
3235
                        (JCC_Z << 1),
3236
                        (JCC_BE << 1),
3237
                        (JCC_P << 1),
3238
                    };
3239
                    op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
3240
                    gen_setcc(s, op1);
3241
                    gen_op_fcmov_ST0_STN_T0(opreg);
3242
                }
3243
                break;
3244
            default:
3245
                goto illegal_op;
3246
            }
3247
        }
3248
#ifdef USE_CODE_COPY
3249
        s->tb->cflags |= CF_TB_FP_USED;
3250
#endif
3251
        break;
3252
        /************************/
3253
        /* string ops */
3254

    
3255
    case 0xa4: /* movsS */
3256
    case 0xa5:
3257
        if ((b & 1) == 0)
3258
            ot = OT_BYTE;
3259
        else
3260
            ot = dflag ? OT_LONG : OT_WORD;
3261

    
3262
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3263
            gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3264
        } else {
3265
            gen_movs(s, ot);
3266
        }
3267
        break;
3268
        
3269
    case 0xaa: /* stosS */
3270
    case 0xab:
3271
        if ((b & 1) == 0)
3272
            ot = OT_BYTE;
3273
        else
3274
            ot = dflag ? OT_LONG : OT_WORD;
3275

    
3276
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3277
            gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3278
        } else {
3279
            gen_stos(s, ot);
3280
        }
3281
        break;
3282
    case 0xac: /* lodsS */
3283
    case 0xad:
3284
        if ((b & 1) == 0)
3285
            ot = OT_BYTE;
3286
        else
3287
            ot = dflag ? OT_LONG : OT_WORD;
3288
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3289
            gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3290
        } else {
3291
            gen_lods(s, ot);
3292
        }
3293
        break;
3294
    case 0xae: /* scasS */
3295
    case 0xaf:
3296
        if ((b & 1) == 0)
3297
            ot = OT_BYTE;
3298
        else
3299
                ot = dflag ? OT_LONG : OT_WORD;
3300
        if (prefixes & PREFIX_REPNZ) {
3301
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3302
        } else if (prefixes & PREFIX_REPZ) {
3303
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3304
        } else {
3305
            gen_scas(s, ot);
3306
            s->cc_op = CC_OP_SUBB + ot;
3307
        }
3308
        break;
3309

    
3310
    case 0xa6: /* cmpsS */
3311
    case 0xa7:
3312
        if ((b & 1) == 0)
3313
            ot = OT_BYTE;
3314
        else
3315
            ot = dflag ? OT_LONG : OT_WORD;
3316
        if (prefixes & PREFIX_REPNZ) {
3317
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3318
        } else if (prefixes & PREFIX_REPZ) {
3319
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3320
        } else {
3321
            gen_cmps(s, ot);
3322
            s->cc_op = CC_OP_SUBB + ot;
3323
        }
3324
        break;
3325
    case 0x6c: /* insS */
3326
    case 0x6d:
3327
        if ((b & 1) == 0)
3328
            ot = OT_BYTE;
3329
        else
3330
            ot = dflag ? OT_LONG : OT_WORD;
3331
        gen_check_io(s, ot, 1, pc_start - s->cs_base);
3332
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3333
            gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3334
        } else {
3335
            gen_ins(s, ot);
3336
        }
3337
        break;
3338
    case 0x6e: /* outsS */
3339
    case 0x6f:
3340
        if ((b & 1) == 0)
3341
            ot = OT_BYTE;
3342
        else
3343
            ot = dflag ? OT_LONG : OT_WORD;
3344
        gen_check_io(s, ot, 1, pc_start - s->cs_base);
3345
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3346
            gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3347
        } else {
3348
            gen_outs(s, ot);
3349
        }
3350
        break;
3351

    
3352
        /************************/
3353
        /* port I/O */
3354
    case 0xe4:
3355
    case 0xe5:
3356
        if ((b & 1) == 0)
3357
            ot = OT_BYTE;
3358
        else
3359
            ot = dflag ? OT_LONG : OT_WORD;
3360
        val = ldub_code(s->pc++);
3361
        gen_op_movl_T0_im(val);
3362
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
3363
        gen_op_in[ot]();
3364
        gen_op_mov_reg_T1[ot][R_EAX]();
3365
        break;
3366
    case 0xe6:
3367
    case 0xe7:
3368
        if ((b & 1) == 0)
3369
            ot = OT_BYTE;
3370
        else
3371
            ot = dflag ? OT_LONG : OT_WORD;
3372
        val = ldub_code(s->pc++);
3373
        gen_op_movl_T0_im(val);
3374
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
3375
        gen_op_mov_TN_reg[ot][1][R_EAX]();
3376
        gen_op_out[ot]();
3377
        break;
3378
    case 0xec:
3379
    case 0xed:
3380
        if ((b & 1) == 0)
3381
            ot = OT_BYTE;
3382
        else
3383
            ot = dflag ? OT_LONG : OT_WORD;
3384
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3385
        gen_op_andl_T0_ffff();
3386
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
3387
        gen_op_in[ot]();
3388
        gen_op_mov_reg_T1[ot][R_EAX]();
3389
        break;
3390
    case 0xee:
3391
    case 0xef:
3392
        if ((b & 1) == 0)
3393
            ot = OT_BYTE;
3394
        else
3395
            ot = dflag ? OT_LONG : OT_WORD;
3396
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3397
        gen_op_andl_T0_ffff();
3398
        gen_check_io(s, ot, 0, pc_start - s->cs_base);
3399
        gen_op_mov_TN_reg[ot][1][R_EAX]();
3400
        gen_op_out[ot]();
3401
        break;
3402

    
3403
        /************************/
3404
        /* control */
3405
    case 0xc2: /* ret im */
3406
        val = ldsw_code(s->pc);
3407
        s->pc += 2;
3408
        gen_pop_T0(s);
3409
        gen_stack_update(s, val + (2 << s->dflag));
3410
        if (s->dflag == 0)
3411
            gen_op_andl_T0_ffff();
3412
        gen_op_jmp_T0();
3413
        gen_eob(s);
3414
        break;
3415
    case 0xc3: /* ret */
3416
        gen_pop_T0(s);
3417
        gen_pop_update(s);
3418
        if (s->dflag == 0)
3419
            gen_op_andl_T0_ffff();
3420
        gen_op_jmp_T0();
3421
        gen_eob(s);
3422
        break;
3423
    case 0xca: /* lret im */
3424
        val = ldsw_code(s->pc);
3425
        s->pc += 2;
3426
    do_lret:
3427
        if (s->pe && !s->vm86) {
3428
            if (s->cc_op != CC_OP_DYNAMIC)
3429
                gen_op_set_cc_op(s->cc_op);
3430
            gen_op_jmp_im(pc_start - s->cs_base);
3431
            gen_op_lret_protected(s->dflag, val);
3432
        } else {
3433
            gen_stack_A0(s);
3434
            /* pop offset */
3435
            gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3436
            if (s->dflag == 0)
3437
                gen_op_andl_T0_ffff();
3438
            /* NOTE: keeping EIP updated is not a problem in case of
3439
               exception */
3440
            gen_op_jmp_T0();
3441
            /* pop selector */
3442
            gen_op_addl_A0_im(2 << s->dflag);
3443
            gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3444
            gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3445
            /* add stack offset */
3446
            gen_stack_update(s, val + (4 << s->dflag));
3447
        }
3448
        gen_eob(s);
3449
        break;
3450
    case 0xcb: /* lret */
3451
        val = 0;
3452
        goto do_lret;
3453
    case 0xcf: /* iret */
3454
        if (!s->pe) {
3455
            /* real mode */
3456
            gen_op_iret_real(s->dflag);
3457
            s->cc_op = CC_OP_EFLAGS;
3458
        } else if (s->vm86) {
3459
            if (s->iopl != 3) {
3460
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3461
            } else {
3462
                gen_op_iret_real(s->dflag);
3463
                s->cc_op = CC_OP_EFLAGS;
3464
            }
3465
        } else {
3466
            if (s->cc_op != CC_OP_DYNAMIC)
3467
                gen_op_set_cc_op(s->cc_op);
3468
            gen_op_jmp_im(pc_start - s->cs_base);
3469
            gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
3470
            s->cc_op = CC_OP_EFLAGS;
3471
        }
3472
        gen_eob(s);
3473
        break;
3474
    case 0xe8: /* call im */
3475
        {
3476
            unsigned int next_eip;
3477
            ot = dflag ? OT_LONG : OT_WORD;
3478
            val = insn_get(s, ot);
3479
            next_eip = s->pc - s->cs_base;
3480
            val += next_eip;
3481
            if (s->dflag == 0)
3482
                val &= 0xffff;
3483
            gen_op_movl_T0_im(next_eip);
3484
            gen_push_T0(s);
3485
            gen_jmp(s, val);
3486
        }
3487
        break;
3488
    case 0x9a: /* lcall im */
3489
        {
3490
            unsigned int selector, offset;
3491

    
3492
            ot = dflag ? OT_LONG : OT_WORD;
3493
            offset = insn_get(s, ot);
3494
            selector = insn_get(s, OT_WORD);
3495
            
3496
            gen_op_movl_T0_im(selector);
3497
            gen_op_movl_T1_im(offset);
3498
        }
3499
        goto do_lcall;
3500
    case 0xe9: /* jmp */
3501
        ot = dflag ? OT_LONG : OT_WORD;
3502
        val = insn_get(s, ot);
3503
        val += s->pc - s->cs_base;
3504
        if (s->dflag == 0)
3505
            val = val & 0xffff;
3506
        gen_jmp(s, val);
3507
        break;
3508
    case 0xea: /* ljmp im */
3509
        {
3510
            unsigned int selector, offset;
3511

    
3512
            ot = dflag ? OT_LONG : OT_WORD;
3513
            offset = insn_get(s, ot);
3514
            selector = insn_get(s, OT_WORD);
3515
            
3516
            gen_op_movl_T0_im(selector);
3517
            gen_op_movl_T1_im(offset);
3518
        }
3519
        goto do_ljmp;
3520
    case 0xeb: /* jmp Jb */
3521
        val = (int8_t)insn_get(s, OT_BYTE);
3522
        val += s->pc - s->cs_base;
3523
        if (s->dflag == 0)
3524
            val = val & 0xffff;
3525
        gen_jmp(s, val);
3526
        break;
3527
    case 0x70 ... 0x7f: /* jcc Jb */
3528
        val = (int8_t)insn_get(s, OT_BYTE);
3529
        goto do_jcc;
3530
    case 0x180 ... 0x18f: /* jcc Jv */
3531
        if (dflag) {
3532
            val = insn_get(s, OT_LONG);
3533
        } else {
3534
            val = (int16_t)insn_get(s, OT_WORD); 
3535
        }
3536
    do_jcc:
3537
        next_eip = s->pc - s->cs_base;
3538
        val += next_eip;
3539
        if (s->dflag == 0)
3540
            val &= 0xffff;
3541
        gen_jcc(s, b, val, next_eip);
3542
        break;
3543

    
3544
    case 0x190 ... 0x19f: /* setcc Gv */
3545
        modrm = ldub_code(s->pc++);
3546
        gen_setcc(s, b);
3547
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3548
        break;
3549
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3550
        ot = dflag ? OT_LONG : OT_WORD;
3551
        modrm = ldub_code(s->pc++);
3552
        reg = (modrm >> 3) & 7;
3553
        mod = (modrm >> 6) & 3;
3554
        gen_setcc(s, b);
3555
        if (mod != 3) {
3556
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3557
            gen_op_ld_T1_A0[ot + s->mem_index]();
3558
        } else {
3559
            rm = modrm & 7;
3560
            gen_op_mov_TN_reg[ot][1][rm]();
3561
        }
3562
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3563
        break;
3564
        
3565
        /************************/
3566
        /* flags */
3567
    case 0x9c: /* pushf */
3568
        if (s->vm86 && s->iopl != 3) {
3569
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3570
        } else {
3571
            if (s->cc_op != CC_OP_DYNAMIC)
3572
                gen_op_set_cc_op(s->cc_op);
3573
            gen_op_movl_T0_eflags();
3574
            gen_push_T0(s);
3575
        }
3576
        break;
3577
    case 0x9d: /* popf */
3578
        if (s->vm86 && s->iopl != 3) {
3579
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3580
        } else {
3581
            gen_pop_T0(s);
3582
            if (s->cpl == 0) {
3583
                if (s->dflag) {
3584
                    gen_op_movl_eflags_T0_cpl0();
3585
                } else {
3586
                    gen_op_movw_eflags_T0_cpl0();
3587
                }
3588
            } else {
3589
                if (s->cpl <= s->iopl) {
3590
                    if (s->dflag) {
3591
                        gen_op_movl_eflags_T0_io();
3592
                    } else {
3593
                        gen_op_movw_eflags_T0_io();
3594
                    }
3595
                } else {
3596
                    if (s->dflag) {
3597
                        gen_op_movl_eflags_T0();
3598
                    } else {
3599
                        gen_op_movw_eflags_T0();
3600
                    }
3601
                }
3602
            }
3603
            gen_pop_update(s);
3604
            s->cc_op = CC_OP_EFLAGS;
3605
            /* abort translation because TF flag may change */
3606
            gen_op_jmp_im(s->pc - s->cs_base);
3607
            gen_eob(s);
3608
        }
3609
        break;
3610
    case 0x9e: /* sahf */
3611
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3612
        if (s->cc_op != CC_OP_DYNAMIC)
3613
            gen_op_set_cc_op(s->cc_op);
3614
        gen_op_movb_eflags_T0();
3615
        s->cc_op = CC_OP_EFLAGS;
3616
        break;
3617
    case 0x9f: /* lahf */
3618
        if (s->cc_op != CC_OP_DYNAMIC)
3619
            gen_op_set_cc_op(s->cc_op);
3620
        gen_op_movl_T0_eflags();
3621
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3622
        break;
3623
    case 0xf5: /* cmc */
3624
        if (s->cc_op != CC_OP_DYNAMIC)
3625
            gen_op_set_cc_op(s->cc_op);
3626
        gen_op_cmc();
3627
        s->cc_op = CC_OP_EFLAGS;
3628
        break;
3629
    case 0xf8: /* clc */
3630
        if (s->cc_op != CC_OP_DYNAMIC)
3631
            gen_op_set_cc_op(s->cc_op);
3632
        gen_op_clc();
3633
        s->cc_op = CC_OP_EFLAGS;
3634
        break;
3635
    case 0xf9: /* stc */
3636
        if (s->cc_op != CC_OP_DYNAMIC)
3637
            gen_op_set_cc_op(s->cc_op);
3638
        gen_op_stc();
3639
        s->cc_op = CC_OP_EFLAGS;
3640
        break;
3641
    case 0xfc: /* cld */
3642
        gen_op_cld();
3643
        break;
3644
    case 0xfd: /* std */
3645
        gen_op_std();
3646
        break;
3647

    
3648
        /************************/
3649
        /* bit operations */
3650
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
3651
        ot = dflag ? OT_LONG : OT_WORD;
3652
        modrm = ldub_code(s->pc++);
3653
        op = (modrm >> 3) & 7;
3654
        mod = (modrm >> 6) & 3;
3655
        rm = modrm & 7;
3656
        if (mod != 3) {
3657
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3658
            gen_op_ld_T0_A0[ot + s->mem_index]();
3659
        } else {
3660
            gen_op_mov_TN_reg[ot][0][rm]();
3661
        }
3662
        /* load shift */
3663
        val = ldub_code(s->pc++);
3664
        gen_op_movl_T1_im(val);
3665
        if (op < 4)
3666
            goto illegal_op;
3667
        op -= 4;
3668
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3669
        s->cc_op = CC_OP_SARB + ot;
3670
        if (op != 0) {
3671
            if (mod != 3)
3672
                gen_op_st_T0_A0[ot + s->mem_index]();
3673
            else
3674
                gen_op_mov_reg_T0[ot][rm]();
3675
            gen_op_update_bt_cc();
3676
        }
3677
        break;
3678
    case 0x1a3: /* bt Gv, Ev */
3679
        op = 0;
3680
        goto do_btx;
3681
    case 0x1ab: /* bts */
3682
        op = 1;
3683
        goto do_btx;
3684
    case 0x1b3: /* btr */
3685
        op = 2;
3686
        goto do_btx;
3687
    case 0x1bb: /* btc */
3688
        op = 3;
3689
    do_btx:
3690
        ot = dflag ? OT_LONG : OT_WORD;
3691
        modrm = ldub_code(s->pc++);
3692
        reg = (modrm >> 3) & 7;
3693
        mod = (modrm >> 6) & 3;
3694
        rm = modrm & 7;
3695
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3696
        if (mod != 3) {
3697
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3698
            /* specific case: we need to add a displacement */
3699
            if (ot == OT_WORD)
3700
                gen_op_add_bitw_A0_T1();
3701
            else
3702
                gen_op_add_bitl_A0_T1();
3703
            gen_op_ld_T0_A0[ot + s->mem_index]();
3704
        } else {
3705
            gen_op_mov_TN_reg[ot][0][rm]();
3706
        }
3707
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3708
        s->cc_op = CC_OP_SARB + ot;
3709
        if (op != 0) {
3710
            if (mod != 3)
3711
                gen_op_st_T0_A0[ot + s->mem_index]();
3712
            else
3713
                gen_op_mov_reg_T0[ot][rm]();
3714
            gen_op_update_bt_cc();
3715
        }
3716
        break;
3717
    case 0x1bc: /* bsf */
3718
    case 0x1bd: /* bsr */
3719
        ot = dflag ? OT_LONG : OT_WORD;
3720
        modrm = ldub_code(s->pc++);
3721
        reg = (modrm >> 3) & 7;
3722
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3723
        /* NOTE: in order to handle the 0 case, we must load the
3724
           result. It could be optimized with a generated jump */
3725
        gen_op_mov_TN_reg[ot][1][reg]();
3726
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3727
        gen_op_mov_reg_T1[ot][reg]();
3728
        s->cc_op = CC_OP_LOGICB + ot;
3729
        break;
3730
        /************************/
3731
        /* bcd */
3732
    case 0x27: /* daa */
3733
        if (s->cc_op != CC_OP_DYNAMIC)
3734
            gen_op_set_cc_op(s->cc_op);
3735
        gen_op_daa();
3736
        s->cc_op = CC_OP_EFLAGS;
3737
        break;
3738
    case 0x2f: /* das */
3739
        if (s->cc_op != CC_OP_DYNAMIC)
3740
            gen_op_set_cc_op(s->cc_op);
3741
        gen_op_das();
3742
        s->cc_op = CC_OP_EFLAGS;
3743
        break;
3744
    case 0x37: /* aaa */
3745
        if (s->cc_op != CC_OP_DYNAMIC)
3746
            gen_op_set_cc_op(s->cc_op);
3747
        gen_op_aaa();
3748
        s->cc_op = CC_OP_EFLAGS;
3749
        break;
3750
    case 0x3f: /* aas */
3751
        if (s->cc_op != CC_OP_DYNAMIC)
3752
            gen_op_set_cc_op(s->cc_op);
3753
        gen_op_aas();
3754
        s->cc_op = CC_OP_EFLAGS;
3755
        break;
3756
    case 0xd4: /* aam */
3757
        val = ldub_code(s->pc++);
3758
        gen_op_aam(val);
3759
        s->cc_op = CC_OP_LOGICB;
3760
        break;
3761
    case 0xd5: /* aad */
3762
        val = ldub_code(s->pc++);
3763
        gen_op_aad(val);
3764
        s->cc_op = CC_OP_LOGICB;
3765
        break;
3766
        /************************/
3767
        /* misc */
3768
    case 0x90: /* nop */
3769
        /* XXX: correct lock test for all insn */
3770
        if (prefixes & PREFIX_LOCK)
3771
            goto illegal_op;
3772
        break;
3773
    case 0x9b: /* fwait */
3774
        if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == 
3775
            (HF_MP_MASK | HF_TS_MASK)) {
3776
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3777
        } else {
3778
            if (s->cc_op != CC_OP_DYNAMIC)
3779
                gen_op_set_cc_op(s->cc_op);
3780
            gen_op_jmp_im(pc_start - s->cs_base);
3781
            gen_op_fwait();
3782
        }
3783
        break;
3784
    case 0xcc: /* int3 */
3785
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3786
        break;
3787
    case 0xcd: /* int N */
3788
        val = ldub_code(s->pc++);
3789
        if (s->vm86 && s->iopl != 3) {
3790
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
3791
        } else {
3792
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3793
        }
3794
        break;
3795
    case 0xce: /* into */
3796
        if (s->cc_op != CC_OP_DYNAMIC)
3797
            gen_op_set_cc_op(s->cc_op);
3798
        gen_op_into(s->pc - s->cs_base);
3799
        break;
3800
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
3801
        gen_debug(s, pc_start - s->cs_base);
3802
        break;
3803
    case 0xfa: /* cli */
3804
        if (!s->vm86) {
3805
            if (s->cpl <= s->iopl) {
3806
                gen_op_cli();
3807
            } else {
3808
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3809
            }
3810
        } else {
3811
            if (s->iopl == 3) {
3812
                gen_op_cli();
3813
            } else {
3814
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3815
            }
3816
        }
3817
        break;
3818
    case 0xfb: /* sti */
3819
        if (!s->vm86) {
3820
            if (s->cpl <= s->iopl) {
3821
            gen_sti:
3822
                gen_op_sti();
3823
                /* interruptions are enabled only the first insn after sti */
3824
                /* If several instructions disable interrupts, only the
3825
                   _first_ does it */
3826
                if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3827
                    gen_op_set_inhibit_irq();
3828
                /* give a chance to handle pending irqs */
3829
                gen_op_jmp_im(s->pc - s->cs_base);
3830
                gen_eob(s);
3831
            } else {
3832
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3833
            }
3834
        } else {
3835
            if (s->iopl == 3) {
3836
                goto gen_sti;
3837
            } else {
3838
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3839
            }
3840
        }
3841
        break;
3842
    case 0x62: /* bound */
3843
        ot = dflag ? OT_LONG : OT_WORD;
3844
        modrm = ldub_code(s->pc++);
3845
        reg = (modrm >> 3) & 7;
3846
        mod = (modrm >> 6) & 3;
3847
        if (mod == 3)
3848
            goto illegal_op;
3849
        gen_op_mov_TN_reg[ot][0][reg]();
3850
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3851
        if (ot == OT_WORD)
3852
            gen_op_boundw(pc_start - s->cs_base);
3853
        else
3854
            gen_op_boundl(pc_start - s->cs_base);
3855
        break;
3856
    case 0x1c8 ... 0x1cf: /* bswap reg */
3857
        reg = b & 7;
3858
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3859
        gen_op_bswapl_T0();
3860
        gen_op_mov_reg_T0[OT_LONG][reg]();
3861
        break;
3862
    case 0xd6: /* salc */
3863
        if (s->cc_op != CC_OP_DYNAMIC)
3864
            gen_op_set_cc_op(s->cc_op);
3865
        gen_op_salc();
3866
        break;
3867
    case 0xe0: /* loopnz */
3868
    case 0xe1: /* loopz */
3869
        if (s->cc_op != CC_OP_DYNAMIC)
3870
            gen_op_set_cc_op(s->cc_op);
3871
        /* FALL THRU */
3872
    case 0xe2: /* loop */
3873
    case 0xe3: /* jecxz */
3874
        val = (int8_t)insn_get(s, OT_BYTE);
3875
        next_eip = s->pc - s->cs_base;
3876
        val += next_eip;
3877
        if (s->dflag == 0)
3878
            val &= 0xffff;
3879
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3880
        gen_eob(s);
3881
        break;
3882
    case 0x130: /* wrmsr */
3883
    case 0x132: /* rdmsr */
3884
        if (s->cpl != 0) {
3885
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3886
        } else {
3887
            if (b & 2)
3888
                gen_op_rdmsr();
3889
            else
3890
                gen_op_wrmsr();
3891
        }
3892
        break;
3893
    case 0x131: /* rdtsc */
3894
        gen_op_rdtsc();
3895
        break;
3896
    case 0x134: /* sysenter */
3897
        if (!s->pe) {
3898
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3899
        } else {
3900
            if (s->cc_op != CC_OP_DYNAMIC) {
3901
                gen_op_set_cc_op(s->cc_op);
3902
                s->cc_op = CC_OP_DYNAMIC;
3903
            }
3904
            gen_op_jmp_im(pc_start - s->cs_base);
3905
            gen_op_sysenter();
3906
            gen_eob(s);
3907
        }
3908
        break;
3909
    case 0x135: /* sysexit */
3910
        if (!s->pe) {
3911
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3912
        } else {
3913
            if (s->cc_op != CC_OP_DYNAMIC) {
3914
                gen_op_set_cc_op(s->cc_op);
3915
                s->cc_op = CC_OP_DYNAMIC;
3916
            }
3917
            gen_op_jmp_im(pc_start - s->cs_base);
3918
            gen_op_sysexit();
3919
            gen_eob(s);
3920
        }
3921
        break;
3922
    case 0x1a2: /* cpuid */
3923
        gen_op_cpuid();
3924
        break;
3925
    case 0xf4: /* hlt */
3926
        if (s->cpl != 0) {
3927
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3928
        } else {
3929
            if (s->cc_op != CC_OP_DYNAMIC)
3930
                gen_op_set_cc_op(s->cc_op);
3931
            gen_op_jmp_im(s->pc - s->cs_base);
3932
            gen_op_hlt();
3933
            s->is_jmp = 3;
3934
        }
3935
        break;
3936
    case 0x100:
3937
        modrm = ldub_code(s->pc++);
3938
        mod = (modrm >> 6) & 3;
3939
        op = (modrm >> 3) & 7;
3940
        switch(op) {
3941
        case 0: /* sldt */
3942
            if (!s->pe || s->vm86)
3943
                goto illegal_op;
3944
            gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3945
            ot = OT_WORD;
3946
            if (mod == 3)
3947
                ot += s->dflag;
3948
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3949
            break;
3950
        case 2: /* lldt */
3951
            if (!s->pe || s->vm86)
3952
                goto illegal_op;
3953
            if (s->cpl != 0) {
3954
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3955
            } else {
3956
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3957
                gen_op_jmp_im(pc_start - s->cs_base);
3958
                gen_op_lldt_T0();
3959
            }
3960
            break;
3961
        case 1: /* str */
3962
            if (!s->pe || s->vm86)
3963
                goto illegal_op;
3964
            gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3965
            ot = OT_WORD;
3966
            if (mod == 3)
3967
                ot += s->dflag;
3968
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3969
            break;
3970
        case 3: /* ltr */
3971
            if (!s->pe || s->vm86)
3972
                goto illegal_op;
3973
            if (s->cpl != 0) {
3974
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3975
            } else {
3976
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3977
                gen_op_jmp_im(pc_start - s->cs_base);
3978
                gen_op_ltr_T0();
3979
            }
3980
            break;
3981
        case 4: /* verr */
3982
        case 5: /* verw */
3983
            if (!s->pe || s->vm86)
3984
                goto illegal_op;
3985
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3986
            if (s->cc_op != CC_OP_DYNAMIC)
3987
                gen_op_set_cc_op(s->cc_op);
3988
            if (op == 4)
3989
                gen_op_verr();
3990
            else
3991
                gen_op_verw();
3992
            s->cc_op = CC_OP_EFLAGS;
3993
            break;
3994
        default:
3995
            goto illegal_op;
3996
        }
3997
        break;
3998
    case 0x101:
3999
        modrm = ldub_code(s->pc++);
4000
        mod = (modrm >> 6) & 3;
4001
        op = (modrm >> 3) & 7;
4002
        switch(op) {
4003
        case 0: /* sgdt */
4004
        case 1: /* sidt */
4005
            if (mod == 3)
4006
                goto illegal_op;
4007
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4008
            if (op == 0)
4009
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
4010
            else
4011
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
4012
            gen_op_st_T0_A0[OT_WORD + s->mem_index]();
4013
            gen_op_addl_A0_im(2);
4014
            if (op == 0)
4015
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
4016
            else
4017
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
4018
            if (!s->dflag)
4019
                gen_op_andl_T0_im(0xffffff);
4020
            gen_op_st_T0_A0[OT_LONG + s->mem_index]();
4021
            break;
4022
        case 2: /* lgdt */
4023
        case 3: /* lidt */
4024
            if (mod == 3)
4025
                goto illegal_op;
4026
            if (s->cpl != 0) {
4027
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4028
            } else {
4029
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4030
                gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
4031
                gen_op_addl_A0_im(2);
4032
                gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
4033
                if (!s->dflag)
4034
                    gen_op_andl_T0_im(0xffffff);
4035
                if (op == 2) {
4036
                    gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
4037
                    gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
4038
                } else {
4039
                    gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
4040
                    gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
4041
                }
4042
            }
4043
            break;
4044
        case 4: /* smsw */
4045
            gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
4046
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
4047
            break;
4048
        case 6: /* lmsw */
4049
            if (s->cpl != 0) {
4050
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4051
            } else {
4052
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4053
                gen_op_lmsw_T0();
4054
                gen_op_jmp_im(s->pc - s->cs_base);
4055
                gen_eob(s);
4056
            }
4057
            break;
4058
        case 7: /* invlpg */
4059
            if (s->cpl != 0) {
4060
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4061
            } else {
4062
                if (mod == 3)
4063
                    goto illegal_op;
4064
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4065
                gen_op_invlpg_A0();
4066
                gen_op_jmp_im(s->pc - s->cs_base);
4067
                gen_eob(s);
4068
            }
4069
            break;
4070
        default:
4071
            goto illegal_op;
4072
        }
4073
        break;
4074
    case 0x108: /* invd */
4075
    case 0x109: /* wbinvd */
4076
        if (s->cpl != 0) {
4077
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4078
        } else {
4079
            /* nothing to do */
4080
        }
4081
        break;
4082
    case 0x63: /* arpl */
4083
        if (!s->pe || s->vm86)
4084
            goto illegal_op;
4085
        ot = dflag ? OT_LONG : OT_WORD;
4086
        modrm = ldub_code(s->pc++);
4087
        reg = (modrm >> 3) & 7;
4088
        mod = (modrm >> 6) & 3;
4089
        rm = modrm & 7;
4090
        if (mod != 3) {
4091
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4092
            gen_op_ld_T0_A0[ot + s->mem_index]();
4093
        } else {
4094
            gen_op_mov_TN_reg[ot][0][rm]();
4095
        }
4096
        if (s->cc_op != CC_OP_DYNAMIC)
4097
            gen_op_set_cc_op(s->cc_op);
4098
        gen_op_arpl();
4099
        s->cc_op = CC_OP_EFLAGS;
4100
        if (mod != 3) {
4101
            gen_op_st_T0_A0[ot + s->mem_index]();
4102
        } else {
4103
            gen_op_mov_reg_T0[ot][rm]();
4104
        }
4105
        gen_op_arpl_update();
4106
        break;
4107
    case 0x102: /* lar */
4108
    case 0x103: /* lsl */
4109
        if (!s->pe || s->vm86)
4110
            goto illegal_op;
4111
        ot = dflag ? OT_LONG : OT_WORD;
4112
        modrm = ldub_code(s->pc++);
4113
        reg = (modrm >> 3) & 7;
4114
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4115
        gen_op_mov_TN_reg[ot][1][reg]();
4116
        if (s->cc_op != CC_OP_DYNAMIC)
4117
            gen_op_set_cc_op(s->cc_op);
4118
        if (b == 0x102)
4119
            gen_op_lar();
4120
        else
4121
            gen_op_lsl();
4122
        s->cc_op = CC_OP_EFLAGS;
4123
        gen_op_mov_reg_T1[ot][reg]();
4124
        break;
4125
    case 0x118:
4126
        modrm = ldub_code(s->pc++);
4127
        mod = (modrm >> 6) & 3;
4128
        op = (modrm >> 3) & 7;
4129
        switch(op) {
4130
        case 0: /* prefetchnta */
4131
        case 1: /* prefetchnt0 */
4132
        case 2: /* prefetchnt0 */
4133
        case 3: /* prefetchnt0 */
4134
            if (mod == 3)
4135
                goto illegal_op;
4136
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4137
            /* nothing more to do */
4138
            break;
4139
        default:
4140
            goto illegal_op;
4141
        }
4142
        break;
4143
    case 0x120: /* mov reg, crN */
4144
    case 0x122: /* mov crN, reg */
4145
        if (s->cpl != 0) {
4146
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4147
        } else {
4148
            modrm = ldub_code(s->pc++);
4149
            if ((modrm & 0xc0) != 0xc0)
4150
                goto illegal_op;
4151
            rm = modrm & 7;
4152
            reg = (modrm >> 3) & 7;
4153
            switch(reg) {
4154
            case 0:
4155
            case 2:
4156
            case 3:
4157
            case 4:
4158
                if (b & 2) {
4159
                    gen_op_mov_TN_reg[OT_LONG][0][rm]();
4160
                    gen_op_movl_crN_T0(reg);
4161
                    gen_op_jmp_im(s->pc - s->cs_base);
4162
                    gen_eob(s);
4163
                } else {
4164
                    gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
4165
                    gen_op_mov_reg_T0[OT_LONG][rm]();
4166
                }
4167
                break;
4168
            default:
4169
                goto illegal_op;
4170
            }
4171
        }
4172
        break;
4173
    case 0x121: /* mov reg, drN */
4174
    case 0x123: /* mov drN, reg */
4175
        if (s->cpl != 0) {
4176
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4177
        } else {
4178
            modrm = ldub_code(s->pc++);
4179
            if ((modrm & 0xc0) != 0xc0)
4180
                goto illegal_op;
4181
            rm = modrm & 7;
4182
            reg = (modrm >> 3) & 7;
4183
            /* XXX: do it dynamically with CR4.DE bit */
4184
            if (reg == 4 || reg == 5)
4185
                goto illegal_op;
4186
            if (b & 2) {
4187
                gen_op_mov_TN_reg[OT_LONG][0][rm]();
4188
                gen_op_movl_drN_T0(reg);
4189
                gen_op_jmp_im(s->pc - s->cs_base);
4190
                gen_eob(s);
4191
            } else {
4192
                gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
4193
                gen_op_mov_reg_T0[OT_LONG][rm]();
4194
            }
4195
        }
4196
        break;
4197
    case 0x106: /* clts */
4198
        if (s->cpl != 0) {
4199
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4200
        } else {
4201
            gen_op_clts();
4202
            /* abort block because static cpu state changed */
4203
            gen_op_jmp_im(s->pc - s->cs_base);
4204
            gen_eob(s);
4205
        }
4206
        break;
4207
    default:
4208
        goto illegal_op;
4209
    }
4210
    /* lock generation */
4211
    if (s->prefix & PREFIX_LOCK)
4212
        gen_op_unlock();
4213
    return s->pc;
4214
 illegal_op:
4215
    if (s->prefix & PREFIX_LOCK)
4216
        gen_op_unlock();
4217
    /* XXX: ensure that no lock was generated */
4218
    gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
4219
    return s->pc;
4220
}
4221

    
4222
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
4223
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
4224

    
4225
/* flags read by an operation */
4226
static uint16_t opc_read_flags[NB_OPS] = { 
4227
    [INDEX_op_aas] = CC_A,
4228
    [INDEX_op_aaa] = CC_A,
4229
    [INDEX_op_das] = CC_A | CC_C,
4230
    [INDEX_op_daa] = CC_A | CC_C,
4231

    
4232
    /* subtle: due to the incl/decl implementation, C is used */
4233
    [INDEX_op_update_inc_cc] = CC_C, 
4234

    
4235
    [INDEX_op_into] = CC_O,
4236

    
4237
    [INDEX_op_jb_subb] = CC_C,
4238
    [INDEX_op_jb_subw] = CC_C,
4239
    [INDEX_op_jb_subl] = CC_C,
4240

    
4241
    [INDEX_op_jz_subb] = CC_Z,
4242
    [INDEX_op_jz_subw] = CC_Z,
4243
    [INDEX_op_jz_subl] = CC_Z,
4244

    
4245
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
4246
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
4247
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
4248

    
4249
    [INDEX_op_js_subb] = CC_S,
4250
    [INDEX_op_js_subw] = CC_S,
4251
    [INDEX_op_js_subl] = CC_S,
4252

    
4253
    [INDEX_op_jl_subb] = CC_O | CC_S,
4254
    [INDEX_op_jl_subw] = CC_O | CC_S,
4255
    [INDEX_op_jl_subl] = CC_O | CC_S,
4256

    
4257
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
4258
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
4259
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
4260

    
4261
    [INDEX_op_loopnzw] = CC_Z,
4262
    [INDEX_op_loopnzl] = CC_Z,
4263
    [INDEX_op_loopzw] = CC_Z,
4264
    [INDEX_op_loopzl] = CC_Z,
4265

    
4266
    [INDEX_op_seto_T0_cc] = CC_O,
4267
    [INDEX_op_setb_T0_cc] = CC_C,
4268
    [INDEX_op_setz_T0_cc] = CC_Z,
4269
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
4270
    [INDEX_op_sets_T0_cc] = CC_S,
4271
    [INDEX_op_setp_T0_cc] = CC_P,
4272
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
4273
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
4274

    
4275
    [INDEX_op_setb_T0_subb] = CC_C,
4276
    [INDEX_op_setb_T0_subw] = CC_C,
4277
    [INDEX_op_setb_T0_subl] = CC_C,
4278

    
4279
    [INDEX_op_setz_T0_subb] = CC_Z,
4280
    [INDEX_op_setz_T0_subw] = CC_Z,
4281
    [INDEX_op_setz_T0_subl] = CC_Z,
4282

    
4283
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
4284
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
4285
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
4286

    
4287
    [INDEX_op_sets_T0_subb] = CC_S,
4288
    [INDEX_op_sets_T0_subw] = CC_S,
4289
    [INDEX_op_sets_T0_subl] = CC_S,
4290

    
4291
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
4292
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
4293
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
4294

    
4295
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
4296
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
4297
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
4298

    
4299
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
4300
    [INDEX_op_cmc] = CC_C,
4301
    [INDEX_op_salc] = CC_C,
4302

    
4303
    /* needed for correct flag optimisation before string ops */
4304
    [INDEX_op_jz_ecxw] = CC_OSZAPC,
4305
    [INDEX_op_jz_ecxl] = CC_OSZAPC,
4306
    [INDEX_op_jz_ecxw_im] = CC_OSZAPC,
4307
    [INDEX_op_jz_ecxl_im] = CC_OSZAPC,
4308

    
4309
#define DEF_READF(SUFFIX)\
4310
    [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4311
    [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4312
    [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
4313
    [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4314
    [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4315
    [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
4316
\
4317
    [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4318
    [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4319
    [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
4320
    [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4321
    [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4322
    [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,
4323

    
4324

    
4325
    DEF_READF( )
4326
    DEF_READF(_raw)
4327
#ifndef CONFIG_USER_ONLY
4328
    DEF_READF(_kernel)
4329
    DEF_READF(_user)
4330
#endif
4331
};
4332

    
4333
/* flags written by an operation */
4334
static uint16_t opc_write_flags[NB_OPS] = { 
4335
    [INDEX_op_update2_cc] = CC_OSZAPC,
4336
    [INDEX_op_update1_cc] = CC_OSZAPC,
4337
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
4338
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
4339
    /* subtle: due to the incl/decl implementation, C is used */
4340
    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
4341
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
4342

    
4343
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
4344
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
4345
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
4346
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
4347
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
4348
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
4349
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
4350
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
4351
    
4352
    /* bcd */
4353
    [INDEX_op_aam] = CC_OSZAPC,
4354
    [INDEX_op_aad] = CC_OSZAPC,
4355
    [INDEX_op_aas] = CC_OSZAPC,
4356
    [INDEX_op_aaa] = CC_OSZAPC,
4357
    [INDEX_op_das] = CC_OSZAPC,
4358
    [INDEX_op_daa] = CC_OSZAPC,
4359

    
4360
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
4361
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
4362
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4363
    [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
4364
    [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
4365
    [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
4366
    [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
4367
    [INDEX_op_clc] = CC_C,
4368
    [INDEX_op_stc] = CC_C,
4369
    [INDEX_op_cmc] = CC_C,
4370

    
4371
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
4372
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
4373
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
4374
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
4375
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
4376
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
4377
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
4378
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
4379

    
4380
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
4381
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
4382
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4383
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4384

    
4385
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4386
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4387
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4388

    
4389
    [INDEX_op_cmpxchg8b] = CC_Z,
4390
    [INDEX_op_lar] = CC_Z,
4391
    [INDEX_op_lsl] = CC_Z,
4392
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4393
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4394

    
4395
#define DEF_WRITEF(SUFFIX)\
4396
    [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4397
    [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4398
    [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4399
    [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4400
    [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4401
    [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4402
\
4403
    [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4404
    [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4405
    [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4406
    [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4407
    [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4408
    [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4409
\
4410
    [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4411
    [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4412
    [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4413
    [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4414
    [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4415
    [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4416
\
4417
    [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4418
    [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4419
    [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4420
\
4421
    [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4422
    [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4423
    [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4424
\
4425
    [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4426
    [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4427
    [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4428
\
4429
    [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4430
    [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4431
    [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4432
    [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4433
\
4434
    [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4435
    [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4436
    [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4437
    [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4438
\
4439
    [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
4440
    [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
4441
    [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,
4442

    
4443

    
4444
    DEF_WRITEF( )
4445
    DEF_WRITEF(_raw)
4446
#ifndef CONFIG_USER_ONLY
4447
    DEF_WRITEF(_kernel)
4448
    DEF_WRITEF(_user)
4449
#endif
4450
};
4451

    
4452
/* simpler form of an operation if no flags need to be generated */
4453
static uint16_t opc_simpler[NB_OPS] = { 
4454
    [INDEX_op_update2_cc] = INDEX_op_nop,
4455
    [INDEX_op_update1_cc] = INDEX_op_nop,
4456
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
4457
#if 0
4458
    /* broken: CC_OP logic must be rewritten */
4459
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
4460
#endif
4461

    
4462
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4463
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4464
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4465

    
4466
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4467
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4468
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4469

    
4470
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4471
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4472
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4473

    
4474
#define DEF_SIMPLER(SUFFIX)\
4475
    [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
4476
    [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
4477
    [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
4478
\
4479
    [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
4480
    [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
4481
    [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,
4482

    
4483
    DEF_SIMPLER( )
4484
    DEF_SIMPLER(_raw)
4485
#ifndef CONFIG_USER_ONLY
4486
    DEF_SIMPLER(_kernel)
4487
    DEF_SIMPLER(_user)
4488
#endif
4489
};
4490

    
4491
void optimize_flags_init(void)
4492
{
4493
    int i;
4494
    /* put default values in arrays */
4495
    for(i = 0; i < NB_OPS; i++) {
4496
        if (opc_simpler[i] == 0)
4497
            opc_simpler[i] = i;
4498
    }
4499
}
4500

    
4501
/* CPU flags computation optimization: we move backward thru the
4502
   generated code to see which flags are needed. The operation is
4503
   modified if suitable */
4504
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4505
{
4506
    uint16_t *opc_ptr;
4507
    int live_flags, write_flags, op;
4508

    
4509
    opc_ptr = opc_buf + opc_buf_len;
4510
    /* live_flags contains the flags needed by the next instructions
4511
       in the code. At the end of the bloc, we consider that all the
4512
       flags are live. */
4513
    live_flags = CC_OSZAPC;
4514
    while (opc_ptr > opc_buf) {
4515
        op = *--opc_ptr;
4516
        /* if none of the flags written by the instruction is used,
4517
           then we can try to find a simpler instruction */
4518
        write_flags = opc_write_flags[op];
4519
        if ((live_flags & write_flags) == 0) {
4520
            *opc_ptr = opc_simpler[op];
4521
        }
4522
        /* compute the live flags before the instruction */
4523
        live_flags &= ~write_flags;
4524
        live_flags |= opc_read_flags[op];
4525
    }
4526
}
4527

    
4528
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4529
   basic block 'tb'. If search_pc is TRUE, also generate PC
4530
   information for each intermediate instruction. */
4531
static inline int gen_intermediate_code_internal(CPUState *env,
4532
                                                 TranslationBlock *tb, 
4533
                                                 int search_pc)
4534
{
4535
    DisasContext dc1, *dc = &dc1;
4536
    uint8_t *pc_ptr;
4537
    uint16_t *gen_opc_end;
4538
    int flags, j, lj, cflags;
4539
    uint8_t *pc_start;
4540
    uint8_t *cs_base;
4541
    
4542
    /* generate intermediate code */
4543
    pc_start = (uint8_t *)tb->pc;
4544
    cs_base = (uint8_t *)tb->cs_base;
4545
    flags = tb->flags;
4546
    cflags = tb->cflags;
4547

    
4548
    dc->pe = (flags >> HF_PE_SHIFT) & 1;
4549
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
4550
    dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
4551
    dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
4552
    dc->f_st = 0;
4553
    dc->vm86 = (flags >> VM_SHIFT) & 1;
4554
    dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
4555
    dc->iopl = (flags >> IOPL_SHIFT) & 3;
4556
    dc->tf = (flags >> TF_SHIFT) & 1;
4557
    dc->singlestep_enabled = env->singlestep_enabled;
4558
    dc->cc_op = CC_OP_DYNAMIC;
4559
    dc->cs_base = cs_base;
4560
    dc->tb = tb;
4561
    dc->popl_esp_hack = 0;
4562
    /* select memory access functions */
4563
    dc->mem_index = 0;
4564
    if (flags & HF_SOFTMMU_MASK) {
4565
        if (dc->cpl == 3)
4566
            dc->mem_index = 6;
4567
        else
4568
            dc->mem_index = 3;
4569
    }
4570
    dc->flags = flags;
4571
    dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
4572
                    (flags & HF_INHIBIT_IRQ_MASK)
4573
#ifndef CONFIG_SOFTMMU
4574
                    || (flags & HF_SOFTMMU_MASK)
4575
#endif
4576
                    );
4577
#if 0
4578
    /* check addseg logic */
4579
    if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4580
        printf("ERROR addseg\n");
4581
#endif
4582

    
4583
    gen_opc_ptr = gen_opc_buf;
4584
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4585
    gen_opparam_ptr = gen_opparam_buf;
4586

    
4587
    dc->is_jmp = DISAS_NEXT;
4588
    pc_ptr = pc_start;
4589
    lj = -1;
4590

    
4591
    for(;;) {
4592
        if (env->nb_breakpoints > 0) {
4593
            for(j = 0; j < env->nb_breakpoints; j++) {
4594
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4595
                    gen_debug(dc, pc_ptr - dc->cs_base);
4596
                    break;
4597
                }
4598
            }
4599
        }
4600
        if (search_pc) {
4601
            j = gen_opc_ptr - gen_opc_buf;
4602
            if (lj < j) {
4603
                lj++;
4604
                while (lj < j)
4605
                    gen_opc_instr_start[lj++] = 0;
4606
            }
4607
            gen_opc_pc[lj] = (uint32_t)pc_ptr;
4608
            gen_opc_cc_op[lj] = dc->cc_op;
4609
            gen_opc_instr_start[lj] = 1;
4610
        }
4611
        pc_ptr = disas_insn(dc, pc_ptr);
4612
        /* stop translation if indicated */
4613
        if (dc->is_jmp)
4614
            break;
4615
        /* if single step mode, we generate only one instruction and
4616
           generate an exception */
4617
        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
4618
           the flag and abort the translation to give the irqs a
4619
           change to be happen */
4620
        if (dc->tf || dc->singlestep_enabled || 
4621
            (flags & HF_INHIBIT_IRQ_MASK) ||
4622
            (cflags & CF_SINGLE_INSN)) {
4623
            gen_op_jmp_im(pc_ptr - dc->cs_base);
4624
            gen_eob(dc);
4625
            break;
4626
        }
4627
        /* if too long translation, stop generation too */
4628
        if (gen_opc_ptr >= gen_opc_end ||
4629
            (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
4630
            gen_op_jmp_im(pc_ptr - dc->cs_base);
4631
            gen_eob(dc);
4632
            break;
4633
        }
4634
    }
4635
    *gen_opc_ptr = INDEX_op_end;
4636
    /* we don't forget to fill the last values */
4637
    if (search_pc) {
4638
        j = gen_opc_ptr - gen_opc_buf;
4639
        lj++;
4640
        while (lj <= j)
4641
            gen_opc_instr_start[lj++] = 0;
4642
    }
4643
        
4644
#ifdef DEBUG_DISAS
4645
    if (loglevel & CPU_LOG_TB_CPU) {
4646
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
4647
    }
4648
    if (loglevel & CPU_LOG_TB_IN_ASM) {
4649
        fprintf(logfile, "----------------\n");
4650
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4651
        disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4652
        fprintf(logfile, "\n");
4653
        if (loglevel & CPU_LOG_TB_OP) {
4654
            fprintf(logfile, "OP:\n");
4655
            dump_ops(gen_opc_buf, gen_opparam_buf);
4656
            fprintf(logfile, "\n");
4657
        }
4658
    }
4659
#endif
4660

    
4661
    /* optimize flag computations */
4662
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4663

    
4664
#ifdef DEBUG_DISAS
4665
    if (loglevel & CPU_LOG_TB_OP_OPT) {
4666
        fprintf(logfile, "AFTER FLAGS OPT:\n");
4667
        dump_ops(gen_opc_buf, gen_opparam_buf);
4668
        fprintf(logfile, "\n");
4669
    }
4670
#endif
4671
    if (!search_pc)
4672
        tb->size = pc_ptr - pc_start;
4673
    return 0;
4674
}
4675

    
4676
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4677
{
4678
    return gen_intermediate_code_internal(env, tb, 0);
4679
}
4680

    
4681
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4682
{
4683
    return gen_intermediate_code_internal(env, tb, 1);
4684
}
4685