Statistics
| Branch: | Revision:

root / target-i386 / translate.c @ 0573fbfc

History | View | Annotate | Download (206.1 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
#ifdef TARGET_X86_64
43
#define X86_64_ONLY(x) x
44
#define X86_64_DEF(x...) x
45
#define CODE64(s) ((s)->code64)
46
#define REX_X(s) ((s)->rex_x)
47
#define REX_B(s) ((s)->rex_b)
48
/* XXX: gcc generates push/pop in some opcodes, so we cannot use them */
49
#if 1
50
#define BUGGY_64(x) NULL
51
#endif
52
#else
53
#define X86_64_ONLY(x) NULL
54
#define X86_64_DEF(x...)
55
#define CODE64(s) 0
56
#define REX_X(s) 0
57
#define REX_B(s) 0
58
#endif
59

    
60
#ifdef TARGET_X86_64
61
static int x86_64_hregs;
62
#endif
63

    
64
#ifdef USE_DIRECT_JUMP
65
#define TBPARAM(x)
66
#else
67
#define TBPARAM(x) (long)(x)
68
#endif
69

    
70
typedef struct DisasContext {
71
    /* current insn context */
72
    int override; /* -1 if no override */
73
    int prefix;
74
    int aflag, dflag;
75
    target_ulong pc; /* pc = eip + cs_base */
76
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
77
                   static state change (stop translation) */
78
    /* current block context */
79
    target_ulong cs_base; /* base of CS segment */
80
    int pe;     /* protected mode */
81
    int code32; /* 32 bit code segment */
82
#ifdef TARGET_X86_64
83
    int lma;    /* long mode active */
84
    int code64; /* 64 bit code segment */
85
    int rex_x, rex_b;
86
#endif
87
    int ss32;   /* 32 bit stack segment */
88
    int cc_op;  /* current CC operation */
89
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
90
    int f_st;   /* currently unused */
91
    int vm86;   /* vm86 mode */
92
    int cpl;
93
    int iopl;
94
    int tf;     /* TF cpu flag */
95
    int singlestep_enabled; /* "hardware" single step enabled */
96
    int jmp_opt; /* use direct block chaining for direct jumps */
97
    int mem_index; /* select memory access functions */
98
    uint64_t flags; /* all execution flags */
99
    struct TranslationBlock *tb;
100
    int popl_esp_hack; /* for correct popl with esp base handling */
101
    int rip_offset; /* only used in x86_64, but left for simplicity */
102
    int cpuid_features;
103
    int cpuid_ext_features;
104
} DisasContext;
105

    
106
static void gen_eob(DisasContext *s);
107
static void gen_jmp(DisasContext *s, target_ulong eip);
108
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
109

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

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

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

    
141
#include "gen-op.h"
142

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

    
151
enum {
152
    /* I386 int registers */
153
    OR_EAX,   /* MUST be even numbered */
154
    OR_ECX,
155
    OR_EDX,
156
    OR_EBX,
157
    OR_ESP,
158
    OR_EBP,
159
    OR_ESI,
160
    OR_EDI,
161

    
162
    OR_TMP0 = 16,    /* temporary operand register */
163
    OR_TMP1,
164
    OR_A0, /* temporary register used when doing address evaluation */
165
};
166

    
167
#ifdef TARGET_X86_64
168

    
169
#define NB_OP_SIZES 4
170

    
171
#define DEF_REGS(prefix, suffix) \
172
  prefix ## EAX ## suffix,\
173
  prefix ## ECX ## suffix,\
174
  prefix ## EDX ## suffix,\
175
  prefix ## EBX ## suffix,\
176
  prefix ## ESP ## suffix,\
177
  prefix ## EBP ## suffix,\
178
  prefix ## ESI ## suffix,\
179
  prefix ## EDI ## suffix,\
180
  prefix ## R8 ## suffix,\
181
  prefix ## R9 ## suffix,\
182
  prefix ## R10 ## suffix,\
183
  prefix ## R11 ## suffix,\
184
  prefix ## R12 ## suffix,\
185
  prefix ## R13 ## suffix,\
186
  prefix ## R14 ## suffix,\
187
  prefix ## R15 ## suffix,
188

    
189
#define DEF_BREGS(prefixb, prefixh, suffix)             \
190
                                                        \
191
static void prefixb ## ESP ## suffix ## _wrapper(void)  \
192
{                                                       \
193
    if (x86_64_hregs)                                 \
194
        prefixb ## ESP ## suffix ();                    \
195
    else                                                \
196
        prefixh ## EAX ## suffix ();                    \
197
}                                                       \
198
                                                        \
199
static void prefixb ## EBP ## suffix ## _wrapper(void)  \
200
{                                                       \
201
    if (x86_64_hregs)                                 \
202
        prefixb ## EBP ## suffix ();                    \
203
    else                                                \
204
        prefixh ## ECX ## suffix ();                    \
205
}                                                       \
206
                                                        \
207
static void prefixb ## ESI ## suffix ## _wrapper(void)  \
208
{                                                       \
209
    if (x86_64_hregs)                                 \
210
        prefixb ## ESI ## suffix ();                    \
211
    else                                                \
212
        prefixh ## EDX ## suffix ();                    \
213
}                                                       \
214
                                                        \
215
static void prefixb ## EDI ## suffix ## _wrapper(void)  \
216
{                                                       \
217
    if (x86_64_hregs)                                 \
218
        prefixb ## EDI ## suffix ();                    \
219
    else                                                \
220
        prefixh ## EBX ## suffix ();                    \
221
}
222

    
223
DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0)
224
DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1)
225
DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, )
226
DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, )
227

    
228
#else /* !TARGET_X86_64 */
229

    
230
#define NB_OP_SIZES 3
231

    
232
#define DEF_REGS(prefix, suffix) \
233
  prefix ## EAX ## suffix,\
234
  prefix ## ECX ## suffix,\
235
  prefix ## EDX ## suffix,\
236
  prefix ## EBX ## suffix,\
237
  prefix ## ESP ## suffix,\
238
  prefix ## EBP ## suffix,\
239
  prefix ## ESI ## suffix,\
240
  prefix ## EDI ## suffix,
241

    
242
#endif /* !TARGET_X86_64 */
243

    
244
static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = {
245
    [OT_BYTE] = {
246
        gen_op_movb_EAX_T0,
247
        gen_op_movb_ECX_T0,
248
        gen_op_movb_EDX_T0,
249
        gen_op_movb_EBX_T0,
250
#ifdef TARGET_X86_64
251
        gen_op_movb_ESP_T0_wrapper,
252
        gen_op_movb_EBP_T0_wrapper,
253
        gen_op_movb_ESI_T0_wrapper,
254
        gen_op_movb_EDI_T0_wrapper,
255
        gen_op_movb_R8_T0,
256
        gen_op_movb_R9_T0,
257
        gen_op_movb_R10_T0,
258
        gen_op_movb_R11_T0,
259
        gen_op_movb_R12_T0,
260
        gen_op_movb_R13_T0,
261
        gen_op_movb_R14_T0,
262
        gen_op_movb_R15_T0,
263
#else
264
        gen_op_movh_EAX_T0,
265
        gen_op_movh_ECX_T0,
266
        gen_op_movh_EDX_T0,
267
        gen_op_movh_EBX_T0,
268
#endif
269
    },
270
    [OT_WORD] = {
271
        DEF_REGS(gen_op_movw_, _T0)
272
    },
273
    [OT_LONG] = {
274
        DEF_REGS(gen_op_movl_, _T0)
275
    },
276
#ifdef TARGET_X86_64
277
    [OT_QUAD] = {
278
        DEF_REGS(gen_op_movq_, _T0)
279
    },
280
#endif
281
};
282

    
283
static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = {
284
    [OT_BYTE] = {
285
        gen_op_movb_EAX_T1,
286
        gen_op_movb_ECX_T1,
287
        gen_op_movb_EDX_T1,
288
        gen_op_movb_EBX_T1,
289
#ifdef TARGET_X86_64
290
        gen_op_movb_ESP_T1_wrapper,
291
        gen_op_movb_EBP_T1_wrapper,
292
        gen_op_movb_ESI_T1_wrapper,
293
        gen_op_movb_EDI_T1_wrapper,
294
        gen_op_movb_R8_T1,
295
        gen_op_movb_R9_T1,
296
        gen_op_movb_R10_T1,
297
        gen_op_movb_R11_T1,
298
        gen_op_movb_R12_T1,
299
        gen_op_movb_R13_T1,
300
        gen_op_movb_R14_T1,
301
        gen_op_movb_R15_T1,
302
#else
303
        gen_op_movh_EAX_T1,
304
        gen_op_movh_ECX_T1,
305
        gen_op_movh_EDX_T1,
306
        gen_op_movh_EBX_T1,
307
#endif
308
    },
309
    [OT_WORD] = {
310
        DEF_REGS(gen_op_movw_, _T1)
311
    },
312
    [OT_LONG] = {
313
        DEF_REGS(gen_op_movl_, _T1)
314
    },
315
#ifdef TARGET_X86_64
316
    [OT_QUAD] = {
317
        DEF_REGS(gen_op_movq_, _T1)
318
    },
319
#endif
320
};
321

    
322
static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
323
    [0] = {
324
        DEF_REGS(gen_op_movw_, _A0)
325
    },
326
    [1] = {
327
        DEF_REGS(gen_op_movl_, _A0)
328
    },
329
#ifdef TARGET_X86_64
330
    [2] = {
331
        DEF_REGS(gen_op_movq_, _A0)
332
    },
333
#endif
334
};
335

    
336
static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] =
337
{
338
    [OT_BYTE] = {
339
        {
340
            gen_op_movl_T0_EAX,
341
            gen_op_movl_T0_ECX,
342
            gen_op_movl_T0_EDX,
343
            gen_op_movl_T0_EBX,
344
#ifdef TARGET_X86_64
345
            gen_op_movl_T0_ESP_wrapper,
346
            gen_op_movl_T0_EBP_wrapper,
347
            gen_op_movl_T0_ESI_wrapper,
348
            gen_op_movl_T0_EDI_wrapper,
349
            gen_op_movl_T0_R8,
350
            gen_op_movl_T0_R9,
351
            gen_op_movl_T0_R10,
352
            gen_op_movl_T0_R11,
353
            gen_op_movl_T0_R12,
354
            gen_op_movl_T0_R13,
355
            gen_op_movl_T0_R14,
356
            gen_op_movl_T0_R15,
357
#else
358
            gen_op_movh_T0_EAX,
359
            gen_op_movh_T0_ECX,
360
            gen_op_movh_T0_EDX,
361
            gen_op_movh_T0_EBX,
362
#endif
363
        },
364
        {
365
            gen_op_movl_T1_EAX,
366
            gen_op_movl_T1_ECX,
367
            gen_op_movl_T1_EDX,
368
            gen_op_movl_T1_EBX,
369
#ifdef TARGET_X86_64
370
            gen_op_movl_T1_ESP_wrapper,
371
            gen_op_movl_T1_EBP_wrapper,
372
            gen_op_movl_T1_ESI_wrapper,
373
            gen_op_movl_T1_EDI_wrapper,
374
            gen_op_movl_T1_R8,
375
            gen_op_movl_T1_R9,
376
            gen_op_movl_T1_R10,
377
            gen_op_movl_T1_R11,
378
            gen_op_movl_T1_R12,
379
            gen_op_movl_T1_R13,
380
            gen_op_movl_T1_R14,
381
            gen_op_movl_T1_R15,
382
#else
383
            gen_op_movh_T1_EAX,
384
            gen_op_movh_T1_ECX,
385
            gen_op_movh_T1_EDX,
386
            gen_op_movh_T1_EBX,
387
#endif
388
        },
389
    },
390
    [OT_WORD] = {
391
        {
392
            DEF_REGS(gen_op_movl_T0_, )
393
        },
394
        {
395
            DEF_REGS(gen_op_movl_T1_, )
396
        },
397
    },
398
    [OT_LONG] = {
399
        {
400
            DEF_REGS(gen_op_movl_T0_, )
401
        },
402
        {
403
            DEF_REGS(gen_op_movl_T1_, )
404
        },
405
    },
406
#ifdef TARGET_X86_64
407
    [OT_QUAD] = {
408
        {
409
            DEF_REGS(gen_op_movl_T0_, )
410
        },
411
        {
412
            DEF_REGS(gen_op_movl_T1_, )
413
        },
414
    },
415
#endif
416
};
417

    
418
static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = {
419
    DEF_REGS(gen_op_movl_A0_, )
420
};
421

    
422
static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = {
423
    [0] = {
424
        DEF_REGS(gen_op_addl_A0_, )
425
    },
426
    [1] = {
427
        DEF_REGS(gen_op_addl_A0_, _s1)
428
    },
429
    [2] = {
430
        DEF_REGS(gen_op_addl_A0_, _s2)
431
    },
432
    [3] = {
433
        DEF_REGS(gen_op_addl_A0_, _s3)
434
    },
435
};
436

    
437
#ifdef TARGET_X86_64
438
static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = {
439
    DEF_REGS(gen_op_movq_A0_, )
440
};
441

    
442
static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = {
443
    [0] = {
444
        DEF_REGS(gen_op_addq_A0_, )
445
    },
446
    [1] = {
447
        DEF_REGS(gen_op_addq_A0_, _s1)
448
    },
449
    [2] = {
450
        DEF_REGS(gen_op_addq_A0_, _s2)
451
    },
452
    [3] = {
453
        DEF_REGS(gen_op_addq_A0_, _s3)
454
    },
455
};
456
#endif
457

    
458
static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
459
    [0] = {
460
        DEF_REGS(gen_op_cmovw_, _T1_T0)
461
    },
462
    [1] = {
463
        DEF_REGS(gen_op_cmovl_, _T1_T0)
464
    },
465
#ifdef TARGET_X86_64
466
    [2] = {
467
        DEF_REGS(gen_op_cmovq_, _T1_T0)
468
    },
469
#endif
470
};
471

    
472
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
473
    NULL,
474
    gen_op_orl_T0_T1,
475
    NULL,
476
    NULL,
477
    gen_op_andl_T0_T1,
478
    NULL,
479
    gen_op_xorl_T0_T1,
480
    NULL,
481
};
482

    
483
#define DEF_ARITHC(SUFFIX)\
484
    {\
485
        gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
486
        gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
487
    },\
488
    {\
489
        gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
490
        gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
491
    },\
492
    {\
493
        gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
494
        gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
495
    },\
496
    {\
497
        X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\
498
        X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\
499
    },
500

    
501
static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
502
    DEF_ARITHC( )
503
};
504

    
505
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
506
    DEF_ARITHC(_raw)
507
#ifndef CONFIG_USER_ONLY
508
    DEF_ARITHC(_kernel)
509
    DEF_ARITHC(_user)
510
#endif
511
};
512

    
513
static const int cc_op_arithb[8] = {
514
    CC_OP_ADDB,
515
    CC_OP_LOGICB,
516
    CC_OP_ADDB,
517
    CC_OP_SUBB,
518
    CC_OP_LOGICB,
519
    CC_OP_SUBB,
520
    CC_OP_LOGICB,
521
    CC_OP_SUBB,
522
};
523

    
524
#define DEF_CMPXCHG(SUFFIX)\
525
    gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
526
    gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
527
    gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
528
    X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc),
529

    
530
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
531
    DEF_CMPXCHG( )
532
};
533

    
534
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
535
    DEF_CMPXCHG(_raw)
536
#ifndef CONFIG_USER_ONLY
537
    DEF_CMPXCHG(_kernel)
538
    DEF_CMPXCHG(_user)
539
#endif
540
};
541

    
542
#define DEF_SHIFT(SUFFIX)\
543
    {\
544
        gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
545
        gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
546
        gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
547
        gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
548
        gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
549
        gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
550
        gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
551
        gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
552
    },\
553
    {\
554
        gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
555
        gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
556
        gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
557
        gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
558
        gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
559
        gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
560
        gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
561
        gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
562
    },\
563
    {\
564
        gen_op_roll ## SUFFIX ## _T0_T1_cc,\
565
        gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
566
        gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
567
        gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
568
        gen_op_shll ## SUFFIX ## _T0_T1_cc,\
569
        gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
570
        gen_op_shll ## SUFFIX ## _T0_T1_cc,\
571
        gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
572
    },\
573
    {\
574
        X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\
575
        X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\
576
        X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\
577
        X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\
578
        X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
579
        X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\
580
        X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
581
        X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\
582
    },
583

    
584
static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
585
    DEF_SHIFT( )
586
};
587

    
588
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
589
    DEF_SHIFT(_raw)
590
#ifndef CONFIG_USER_ONLY
591
    DEF_SHIFT(_kernel)
592
    DEF_SHIFT(_user)
593
#endif
594
};
595

    
596
#define DEF_SHIFTD(SUFFIX, op)\
597
    {\
598
        NULL,\
599
        NULL,\
600
    },\
601
    {\
602
        gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
603
        gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
604
     },\
605
    {\
606
        gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
607
        gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
608
    },\
609
    {\
610
X86_64_DEF(gen_op_shldq ## SUFFIX ## _T0_T1_ ## op ## _cc,\
611
           gen_op_shrdq ## SUFFIX ## _T0_T1_ ## op ## _cc,)\
612
    },
613

    
614
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = {
615
    DEF_SHIFTD(, im)
616
};
617

    
618
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
619
    DEF_SHIFTD(, ECX)
620
};
621

    
622
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
623
    DEF_SHIFTD(_raw, im)
624
#ifndef CONFIG_USER_ONLY
625
    DEF_SHIFTD(_kernel, im)
626
    DEF_SHIFTD(_user, im)
627
#endif
628
};
629

    
630
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
631
    DEF_SHIFTD(_raw, ECX)
632
#ifndef CONFIG_USER_ONLY
633
    DEF_SHIFTD(_kernel, ECX)
634
    DEF_SHIFTD(_user, ECX)
635
#endif
636
};
637

    
638
static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
639
    [0] = {
640
        gen_op_btw_T0_T1_cc,
641
        gen_op_btsw_T0_T1_cc,
642
        gen_op_btrw_T0_T1_cc,
643
        gen_op_btcw_T0_T1_cc,
644
    },
645
    [1] = {
646
        gen_op_btl_T0_T1_cc,
647
        gen_op_btsl_T0_T1_cc,
648
        gen_op_btrl_T0_T1_cc,
649
        gen_op_btcl_T0_T1_cc,
650
    },
651
#ifdef TARGET_X86_64
652
    [2] = {
653
        gen_op_btq_T0_T1_cc,
654
        gen_op_btsq_T0_T1_cc,
655
        gen_op_btrq_T0_T1_cc,
656
        gen_op_btcq_T0_T1_cc,
657
    },
658
#endif
659
};
660

    
661
static GenOpFunc *gen_op_add_bit_A0_T1[3] = {
662
    gen_op_add_bitw_A0_T1,
663
    gen_op_add_bitl_A0_T1,
664
    X86_64_ONLY(gen_op_add_bitq_A0_T1),
665
};
666

    
667
static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
668
    [0] = {
669
        gen_op_bsfw_T0_cc,
670
        gen_op_bsrw_T0_cc,
671
    },
672
    [1] = {
673
        gen_op_bsfl_T0_cc,
674
        gen_op_bsrl_T0_cc,
675
    },
676
#ifdef TARGET_X86_64
677
    [2] = {
678
        gen_op_bsfq_T0_cc,
679
        gen_op_bsrq_T0_cc,
680
    },
681
#endif
682
};
683

    
684
static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = {
685
    gen_op_ldsb_raw_T0_A0,
686
    gen_op_ldsw_raw_T0_A0,
687
    X86_64_ONLY(gen_op_ldsl_raw_T0_A0),
688
    NULL,
689
#ifndef CONFIG_USER_ONLY
690
    gen_op_ldsb_kernel_T0_A0,
691
    gen_op_ldsw_kernel_T0_A0,
692
    X86_64_ONLY(gen_op_ldsl_kernel_T0_A0),
693
    NULL,
694

    
695
    gen_op_ldsb_user_T0_A0,
696
    gen_op_ldsw_user_T0_A0,
697
    X86_64_ONLY(gen_op_ldsl_user_T0_A0),
698
    NULL,
699
#endif
700
};
701

    
702
static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = {
703
    gen_op_ldub_raw_T0_A0,
704
    gen_op_lduw_raw_T0_A0,
705
    NULL,
706
    NULL,
707

    
708
#ifndef CONFIG_USER_ONLY
709
    gen_op_ldub_kernel_T0_A0,
710
    gen_op_lduw_kernel_T0_A0,
711
    NULL,
712
    NULL,
713

    
714
    gen_op_ldub_user_T0_A0,
715
    gen_op_lduw_user_T0_A0,
716
    NULL,
717
    NULL,
718
#endif
719
};
720

    
721
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
722
static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = {
723
    gen_op_ldub_raw_T0_A0,
724
    gen_op_lduw_raw_T0_A0,
725
    gen_op_ldl_raw_T0_A0,
726
    X86_64_ONLY(gen_op_ldq_raw_T0_A0),
727

    
728
#ifndef CONFIG_USER_ONLY
729
    gen_op_ldub_kernel_T0_A0,
730
    gen_op_lduw_kernel_T0_A0,
731
    gen_op_ldl_kernel_T0_A0,
732
    X86_64_ONLY(gen_op_ldq_kernel_T0_A0),
733

    
734
    gen_op_ldub_user_T0_A0,
735
    gen_op_lduw_user_T0_A0,
736
    gen_op_ldl_user_T0_A0,
737
    X86_64_ONLY(gen_op_ldq_user_T0_A0),
738
#endif
739
};
740

    
741
static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = {
742
    gen_op_ldub_raw_T1_A0,
743
    gen_op_lduw_raw_T1_A0,
744
    gen_op_ldl_raw_T1_A0,
745
    X86_64_ONLY(gen_op_ldq_raw_T1_A0),
746

    
747
#ifndef CONFIG_USER_ONLY
748
    gen_op_ldub_kernel_T1_A0,
749
    gen_op_lduw_kernel_T1_A0,
750
    gen_op_ldl_kernel_T1_A0,
751
    X86_64_ONLY(gen_op_ldq_kernel_T1_A0),
752

    
753
    gen_op_ldub_user_T1_A0,
754
    gen_op_lduw_user_T1_A0,
755
    gen_op_ldl_user_T1_A0,
756
    X86_64_ONLY(gen_op_ldq_user_T1_A0),
757
#endif
758
};
759

    
760
static GenOpFunc *gen_op_st_T0_A0[3 * 4] = {
761
    gen_op_stb_raw_T0_A0,
762
    gen_op_stw_raw_T0_A0,
763
    gen_op_stl_raw_T0_A0,
764
    X86_64_ONLY(gen_op_stq_raw_T0_A0),
765

    
766
#ifndef CONFIG_USER_ONLY
767
    gen_op_stb_kernel_T0_A0,
768
    gen_op_stw_kernel_T0_A0,
769
    gen_op_stl_kernel_T0_A0,
770
    X86_64_ONLY(gen_op_stq_kernel_T0_A0),
771

    
772
    gen_op_stb_user_T0_A0,
773
    gen_op_stw_user_T0_A0,
774
    gen_op_stl_user_T0_A0,
775
    X86_64_ONLY(gen_op_stq_user_T0_A0),
776
#endif
777
};
778

    
779
static GenOpFunc *gen_op_st_T1_A0[3 * 4] = {
780
    NULL,
781
    gen_op_stw_raw_T1_A0,
782
    gen_op_stl_raw_T1_A0,
783
    X86_64_ONLY(gen_op_stq_raw_T1_A0),
784

    
785
#ifndef CONFIG_USER_ONLY
786
    NULL,
787
    gen_op_stw_kernel_T1_A0,
788
    gen_op_stl_kernel_T1_A0,
789
    X86_64_ONLY(gen_op_stq_kernel_T1_A0),
790

    
791
    NULL,
792
    gen_op_stw_user_T1_A0,
793
    gen_op_stl_user_T1_A0,
794
    X86_64_ONLY(gen_op_stq_user_T1_A0),
795
#endif
796
};
797

    
798
static inline void gen_jmp_im(target_ulong pc)
799
{
800
#ifdef TARGET_X86_64
801
    if (pc == (uint32_t)pc) {
802
        gen_op_movl_eip_im(pc);
803
    } else if (pc == (int32_t)pc) {
804
        gen_op_movq_eip_im(pc);
805
    } else {
806
        gen_op_movq_eip_im64(pc >> 32, pc);
807
    }
808
#else
809
    gen_op_movl_eip_im(pc);
810
#endif
811
}
812

    
813
static inline void gen_string_movl_A0_ESI(DisasContext *s)
814
{
815
    int override;
816

    
817
    override = s->override;
818
#ifdef TARGET_X86_64
819
    if (s->aflag == 2) {
820
        if (override >= 0) {
821
            gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base));
822
            gen_op_addq_A0_reg_sN[0][R_ESI]();
823
        } else {
824
            gen_op_movq_A0_reg[R_ESI]();
825
        }
826
    } else
827
#endif
828
    if (s->aflag) {
829
        /* 32 bit address */
830
        if (s->addseg && override < 0)
831
            override = R_DS;
832
        if (override >= 0) {
833
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
834
            gen_op_addl_A0_reg_sN[0][R_ESI]();
835
        } else {
836
            gen_op_movl_A0_reg[R_ESI]();
837
        }
838
    } else {
839
        /* 16 address, always override */
840
        if (override < 0)
841
            override = R_DS;
842
        gen_op_movl_A0_reg[R_ESI]();
843
        gen_op_andl_A0_ffff();
844
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
845
    }
846
}
847

    
848
static inline void gen_string_movl_A0_EDI(DisasContext *s)
849
{
850
#ifdef TARGET_X86_64
851
    if (s->aflag == 2) {
852
        gen_op_movq_A0_reg[R_EDI]();
853
    } else
854
#endif
855
    if (s->aflag) {
856
        if (s->addseg) {
857
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
858
            gen_op_addl_A0_reg_sN[0][R_EDI]();
859
        } else {
860
            gen_op_movl_A0_reg[R_EDI]();
861
        }
862
    } else {
863
        gen_op_movl_A0_reg[R_EDI]();
864
        gen_op_andl_A0_ffff();
865
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
866
    }
867
}
868

    
869
static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
870
    gen_op_movl_T0_Dshiftb,
871
    gen_op_movl_T0_Dshiftw,
872
    gen_op_movl_T0_Dshiftl,
873
    X86_64_ONLY(gen_op_movl_T0_Dshiftq),
874
};
875

    
876
static GenOpFunc1 *gen_op_jnz_ecx[3] = {
877
    gen_op_jnz_ecxw,
878
    gen_op_jnz_ecxl,
879
    X86_64_ONLY(gen_op_jnz_ecxq),
880
};
881

    
882
static GenOpFunc1 *gen_op_jz_ecx[3] = {
883
    gen_op_jz_ecxw,
884
    gen_op_jz_ecxl,
885
    X86_64_ONLY(gen_op_jz_ecxq),
886
};
887

    
888
static GenOpFunc *gen_op_dec_ECX[3] = {
889
    gen_op_decw_ECX,
890
    gen_op_decl_ECX,
891
    X86_64_ONLY(gen_op_decq_ECX),
892
};
893

    
894
static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
895
    {
896
        gen_op_jnz_subb,
897
        gen_op_jnz_subw,
898
        gen_op_jnz_subl,
899
        X86_64_ONLY(gen_op_jnz_subq),
900
    },
901
    {
902
        gen_op_jz_subb,
903
        gen_op_jz_subw,
904
        gen_op_jz_subl,
905
        X86_64_ONLY(gen_op_jz_subq),
906
    },
907
};
908

    
909
static GenOpFunc *gen_op_in_DX_T0[3] = {
910
    gen_op_inb_DX_T0,
911
    gen_op_inw_DX_T0,
912
    gen_op_inl_DX_T0,
913
};
914

    
915
static GenOpFunc *gen_op_out_DX_T0[3] = {
916
    gen_op_outb_DX_T0,
917
    gen_op_outw_DX_T0,
918
    gen_op_outl_DX_T0,
919
};
920

    
921
static GenOpFunc *gen_op_in[3] = {
922
    gen_op_inb_T0_T1,
923
    gen_op_inw_T0_T1,
924
    gen_op_inl_T0_T1,
925
};
926

    
927
static GenOpFunc *gen_op_out[3] = {
928
    gen_op_outb_T0_T1,
929
    gen_op_outw_T0_T1,
930
    gen_op_outl_T0_T1,
931
};
932

    
933
static GenOpFunc *gen_check_io_T0[3] = {
934
    gen_op_check_iob_T0,
935
    gen_op_check_iow_T0,
936
    gen_op_check_iol_T0,
937
};
938

    
939
static GenOpFunc *gen_check_io_DX[3] = {
940
    gen_op_check_iob_DX,
941
    gen_op_check_iow_DX,
942
    gen_op_check_iol_DX,
943
};
944

    
945
static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
946
{
947
    if (s->pe && (s->cpl > s->iopl || s->vm86)) {
948
        if (s->cc_op != CC_OP_DYNAMIC)
949
            gen_op_set_cc_op(s->cc_op);
950
        gen_jmp_im(cur_eip);
951
        if (use_dx)
952
            gen_check_io_DX[ot]();
953
        else
954
            gen_check_io_T0[ot]();
955
    }
956
}
957

    
958
static inline void gen_movs(DisasContext *s, int ot)
959
{
960
    gen_string_movl_A0_ESI(s);
961
    gen_op_ld_T0_A0[ot + s->mem_index]();
962
    gen_string_movl_A0_EDI(s);
963
    gen_op_st_T0_A0[ot + s->mem_index]();
964
    gen_op_movl_T0_Dshift[ot]();
965
#ifdef TARGET_X86_64
966
    if (s->aflag == 2) {
967
        gen_op_addq_ESI_T0();
968
        gen_op_addq_EDI_T0();
969
    } else
970
#endif
971
    if (s->aflag) {
972
        gen_op_addl_ESI_T0();
973
        gen_op_addl_EDI_T0();
974
    } else {
975
        gen_op_addw_ESI_T0();
976
        gen_op_addw_EDI_T0();
977
    }
978
}
979

    
980
static inline void gen_update_cc_op(DisasContext *s)
981
{
982
    if (s->cc_op != CC_OP_DYNAMIC) {
983
        gen_op_set_cc_op(s->cc_op);
984
        s->cc_op = CC_OP_DYNAMIC;
985
    }
986
}
987

    
988
/* XXX: does not work with gdbstub "ice" single step - not a
989
   serious problem */
990
static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
991
{
992
    int l1, l2;
993

    
994
    l1 = gen_new_label();
995
    l2 = gen_new_label();
996
    gen_op_jnz_ecx[s->aflag](l1);
997
    gen_set_label(l2);
998
    gen_jmp_tb(s, next_eip, 1);
999
    gen_set_label(l1);
1000
    return l2;
1001
}
1002

    
1003
static inline void gen_stos(DisasContext *s, int ot)
1004
{
1005
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1006
    gen_string_movl_A0_EDI(s);
1007
    gen_op_st_T0_A0[ot + s->mem_index]();
1008
    gen_op_movl_T0_Dshift[ot]();
1009
#ifdef TARGET_X86_64
1010
    if (s->aflag == 2) {
1011
        gen_op_addq_EDI_T0();
1012
    } else
1013
#endif
1014
    if (s->aflag) {
1015
        gen_op_addl_EDI_T0();
1016
    } else {
1017
        gen_op_addw_EDI_T0();
1018
    }
1019
}
1020

    
1021
static inline void gen_lods(DisasContext *s, int ot)
1022
{
1023
    gen_string_movl_A0_ESI(s);
1024
    gen_op_ld_T0_A0[ot + s->mem_index]();
1025
    gen_op_mov_reg_T0[ot][R_EAX]();
1026
    gen_op_movl_T0_Dshift[ot]();
1027
#ifdef TARGET_X86_64
1028
    if (s->aflag == 2) {
1029
        gen_op_addq_ESI_T0();
1030
    } else
1031
#endif
1032
    if (s->aflag) {
1033
        gen_op_addl_ESI_T0();
1034
    } else {
1035
        gen_op_addw_ESI_T0();
1036
    }
1037
}
1038

    
1039
static inline void gen_scas(DisasContext *s, int ot)
1040
{
1041
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1042
    gen_string_movl_A0_EDI(s);
1043
    gen_op_ld_T1_A0[ot + s->mem_index]();
1044
    gen_op_cmpl_T0_T1_cc();
1045
    gen_op_movl_T0_Dshift[ot]();
1046
#ifdef TARGET_X86_64
1047
    if (s->aflag == 2) {
1048
        gen_op_addq_EDI_T0();
1049
    } else
1050
#endif
1051
    if (s->aflag) {
1052
        gen_op_addl_EDI_T0();
1053
    } else {
1054
        gen_op_addw_EDI_T0();
1055
    }
1056
}
1057

    
1058
static inline void gen_cmps(DisasContext *s, int ot)
1059
{
1060
    gen_string_movl_A0_ESI(s);
1061
    gen_op_ld_T0_A0[ot + s->mem_index]();
1062
    gen_string_movl_A0_EDI(s);
1063
    gen_op_ld_T1_A0[ot + s->mem_index]();
1064
    gen_op_cmpl_T0_T1_cc();
1065
    gen_op_movl_T0_Dshift[ot]();
1066
#ifdef TARGET_X86_64
1067
    if (s->aflag == 2) {
1068
        gen_op_addq_ESI_T0();
1069
        gen_op_addq_EDI_T0();
1070
    } else
1071
#endif
1072
    if (s->aflag) {
1073
        gen_op_addl_ESI_T0();
1074
        gen_op_addl_EDI_T0();
1075
    } else {
1076
        gen_op_addw_ESI_T0();
1077
        gen_op_addw_EDI_T0();
1078
    }
1079
}
1080

    
1081
static inline void gen_ins(DisasContext *s, int ot)
1082
{
1083
    gen_string_movl_A0_EDI(s);
1084
    gen_op_movl_T0_0();
1085
    gen_op_st_T0_A0[ot + s->mem_index]();
1086
    gen_op_in_DX_T0[ot]();
1087
    gen_op_st_T0_A0[ot + s->mem_index]();
1088
    gen_op_movl_T0_Dshift[ot]();
1089
#ifdef TARGET_X86_64
1090
    if (s->aflag == 2) {
1091
        gen_op_addq_EDI_T0();
1092
    } else
1093
#endif
1094
    if (s->aflag) {
1095
        gen_op_addl_EDI_T0();
1096
    } else {
1097
        gen_op_addw_EDI_T0();
1098
    }
1099
}
1100

    
1101
static inline void gen_outs(DisasContext *s, int ot)
1102
{
1103
    gen_string_movl_A0_ESI(s);
1104
    gen_op_ld_T0_A0[ot + s->mem_index]();
1105
    gen_op_out_DX_T0[ot]();
1106
    gen_op_movl_T0_Dshift[ot]();
1107
#ifdef TARGET_X86_64
1108
    if (s->aflag == 2) {
1109
        gen_op_addq_ESI_T0();
1110
    } else
1111
#endif
1112
    if (s->aflag) {
1113
        gen_op_addl_ESI_T0();
1114
    } else {
1115
        gen_op_addw_ESI_T0();
1116
    }
1117
}
1118

    
1119
/* same method as Valgrind : we generate jumps to current or next
1120
   instruction */
1121
#define GEN_REPZ(op)                                                          \
1122
static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
1123
                                 target_ulong cur_eip, target_ulong next_eip) \
1124
{                                                                             \
1125
    int l2;\
1126
    gen_update_cc_op(s);                                                      \
1127
    l2 = gen_jz_ecx_string(s, next_eip);                                      \
1128
    gen_ ## op(s, ot);                                                        \
1129
    gen_op_dec_ECX[s->aflag]();                                               \
1130
    /* a loop would cause two single step exceptions if ECX = 1               \
1131
       before rep string_insn */                                              \
1132
    if (!s->jmp_opt)                                                          \
1133
        gen_op_jz_ecx[s->aflag](l2);                                          \
1134
    gen_jmp(s, cur_eip);                                                      \
1135
}
1136

    
1137
#define GEN_REPZ2(op)                                                         \
1138
static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
1139
                                   target_ulong cur_eip,                      \
1140
                                   target_ulong next_eip,                     \
1141
                                   int nz)                                    \
1142
{                                                                             \
1143
    int l2;\
1144
    gen_update_cc_op(s);                                                      \
1145
    l2 = gen_jz_ecx_string(s, next_eip);                                      \
1146
    gen_ ## op(s, ot);                                                        \
1147
    gen_op_dec_ECX[s->aflag]();                                               \
1148
    gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
1149
    gen_op_string_jnz_sub[nz][ot](l2);\
1150
    if (!s->jmp_opt)                                                          \
1151
        gen_op_jz_ecx[s->aflag](l2);                                          \
1152
    gen_jmp(s, cur_eip);                                                      \
1153
}
1154

    
1155
GEN_REPZ(movs)
1156
GEN_REPZ(stos)
1157
GEN_REPZ(lods)
1158
GEN_REPZ(ins)
1159
GEN_REPZ(outs)
1160
GEN_REPZ2(scas)
1161
GEN_REPZ2(cmps)
1162

    
1163
enum {
1164
    JCC_O,
1165
    JCC_B,
1166
    JCC_Z,
1167
    JCC_BE,
1168
    JCC_S,
1169
    JCC_P,
1170
    JCC_L,
1171
    JCC_LE,
1172
};
1173

    
1174
static GenOpFunc1 *gen_jcc_sub[4][8] = {
1175
    [OT_BYTE] = {
1176
        NULL,
1177
        gen_op_jb_subb,
1178
        gen_op_jz_subb,
1179
        gen_op_jbe_subb,
1180
        gen_op_js_subb,
1181
        NULL,
1182
        gen_op_jl_subb,
1183
        gen_op_jle_subb,
1184
    },
1185
    [OT_WORD] = {
1186
        NULL,
1187
        gen_op_jb_subw,
1188
        gen_op_jz_subw,
1189
        gen_op_jbe_subw,
1190
        gen_op_js_subw,
1191
        NULL,
1192
        gen_op_jl_subw,
1193
        gen_op_jle_subw,
1194
    },
1195
    [OT_LONG] = {
1196
        NULL,
1197
        gen_op_jb_subl,
1198
        gen_op_jz_subl,
1199
        gen_op_jbe_subl,
1200
        gen_op_js_subl,
1201
        NULL,
1202
        gen_op_jl_subl,
1203
        gen_op_jle_subl,
1204
    },
1205
#ifdef TARGET_X86_64
1206
    [OT_QUAD] = {
1207
        NULL,
1208
        BUGGY_64(gen_op_jb_subq),
1209
        gen_op_jz_subq,
1210
        BUGGY_64(gen_op_jbe_subq),
1211
        gen_op_js_subq,
1212
        NULL,
1213
        BUGGY_64(gen_op_jl_subq),
1214
        BUGGY_64(gen_op_jle_subq),
1215
    },
1216
#endif
1217
};
1218
static GenOpFunc1 *gen_op_loop[3][4] = {
1219
    [0] = {
1220
        gen_op_loopnzw,
1221
        gen_op_loopzw,
1222
        gen_op_jnz_ecxw,
1223
    },
1224
    [1] = {
1225
        gen_op_loopnzl,
1226
        gen_op_loopzl,
1227
        gen_op_jnz_ecxl,
1228
    },
1229
#ifdef TARGET_X86_64
1230
    [2] = {
1231
        gen_op_loopnzq,
1232
        gen_op_loopzq,
1233
        gen_op_jnz_ecxq,
1234
    },
1235
#endif
1236
};
1237

    
1238
static GenOpFunc *gen_setcc_slow[8] = {
1239
    gen_op_seto_T0_cc,
1240
    gen_op_setb_T0_cc,
1241
    gen_op_setz_T0_cc,
1242
    gen_op_setbe_T0_cc,
1243
    gen_op_sets_T0_cc,
1244
    gen_op_setp_T0_cc,
1245
    gen_op_setl_T0_cc,
1246
    gen_op_setle_T0_cc,
1247
};
1248

    
1249
static GenOpFunc *gen_setcc_sub[4][8] = {
1250
    [OT_BYTE] = {
1251
        NULL,
1252
        gen_op_setb_T0_subb,
1253
        gen_op_setz_T0_subb,
1254
        gen_op_setbe_T0_subb,
1255
        gen_op_sets_T0_subb,
1256
        NULL,
1257
        gen_op_setl_T0_subb,
1258
        gen_op_setle_T0_subb,
1259
    },
1260
    [OT_WORD] = {
1261
        NULL,
1262
        gen_op_setb_T0_subw,
1263
        gen_op_setz_T0_subw,
1264
        gen_op_setbe_T0_subw,
1265
        gen_op_sets_T0_subw,
1266
        NULL,
1267
        gen_op_setl_T0_subw,
1268
        gen_op_setle_T0_subw,
1269
    },
1270
    [OT_LONG] = {
1271
        NULL,
1272
        gen_op_setb_T0_subl,
1273
        gen_op_setz_T0_subl,
1274
        gen_op_setbe_T0_subl,
1275
        gen_op_sets_T0_subl,
1276
        NULL,
1277
        gen_op_setl_T0_subl,
1278
        gen_op_setle_T0_subl,
1279
    },
1280
#ifdef TARGET_X86_64
1281
    [OT_QUAD] = {
1282
        NULL,
1283
        gen_op_setb_T0_subq,
1284
        gen_op_setz_T0_subq,
1285
        gen_op_setbe_T0_subq,
1286
        gen_op_sets_T0_subq,
1287
        NULL,
1288
        gen_op_setl_T0_subq,
1289
        gen_op_setle_T0_subq,
1290
    },
1291
#endif
1292
};
1293

    
1294
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1295
    gen_op_fadd_ST0_FT0,
1296
    gen_op_fmul_ST0_FT0,
1297
    gen_op_fcom_ST0_FT0,
1298
    gen_op_fcom_ST0_FT0,
1299
    gen_op_fsub_ST0_FT0,
1300
    gen_op_fsubr_ST0_FT0,
1301
    gen_op_fdiv_ST0_FT0,
1302
    gen_op_fdivr_ST0_FT0,
1303
};
1304

    
1305
/* NOTE the exception in "r" op ordering */
1306
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1307
    gen_op_fadd_STN_ST0,
1308
    gen_op_fmul_STN_ST0,
1309
    NULL,
1310
    NULL,
1311
    gen_op_fsubr_STN_ST0,
1312
    gen_op_fsub_STN_ST0,
1313
    gen_op_fdivr_STN_ST0,
1314
    gen_op_fdiv_STN_ST0,
1315
};
1316

    
1317
/* if d == OR_TMP0, it means memory operand (address in A0) */
1318
static void gen_op(DisasContext *s1, int op, int ot, int d)
1319
{
1320
    GenOpFunc *gen_update_cc;
1321

    
1322
    if (d != OR_TMP0) {
1323
        gen_op_mov_TN_reg[ot][0][d]();
1324
    } else {
1325
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1326
    }
1327
    switch(op) {
1328
    case OP_ADCL:
1329
    case OP_SBBL:
1330
        if (s1->cc_op != CC_OP_DYNAMIC)
1331
            gen_op_set_cc_op(s1->cc_op);
1332
        if (d != OR_TMP0) {
1333
            gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1334
            gen_op_mov_reg_T0[ot][d]();
1335
        } else {
1336
            gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
1337
        }
1338
        s1->cc_op = CC_OP_DYNAMIC;
1339
        goto the_end;
1340
    case OP_ADDL:
1341
        gen_op_addl_T0_T1();
1342
        s1->cc_op = CC_OP_ADDB + ot;
1343
        gen_update_cc = gen_op_update2_cc;
1344
        break;
1345
    case OP_SUBL:
1346
        gen_op_subl_T0_T1();
1347
        s1->cc_op = CC_OP_SUBB + ot;
1348
        gen_update_cc = gen_op_update2_cc;
1349
        break;
1350
    default:
1351
    case OP_ANDL:
1352
    case OP_ORL:
1353
    case OP_XORL:
1354
        gen_op_arith_T0_T1_cc[op]();
1355
        s1->cc_op = CC_OP_LOGICB + ot;
1356
        gen_update_cc = gen_op_update1_cc;
1357
        break;
1358
    case OP_CMPL:
1359
        gen_op_cmpl_T0_T1_cc();
1360
        s1->cc_op = CC_OP_SUBB + ot;
1361
        gen_update_cc = NULL;
1362
        break;
1363
    }
1364
    if (op != OP_CMPL) {
1365
        if (d != OR_TMP0)
1366
            gen_op_mov_reg_T0[ot][d]();
1367
        else
1368
            gen_op_st_T0_A0[ot + s1->mem_index]();
1369
    }
1370
    /* the flags update must happen after the memory write (precise
1371
       exception support) */
1372
    if (gen_update_cc)
1373
        gen_update_cc();
1374
 the_end: ;
1375
}
1376

    
1377
/* if d == OR_TMP0, it means memory operand (address in A0) */
1378
static void gen_inc(DisasContext *s1, int ot, int d, int c)
1379
{
1380
    if (d != OR_TMP0)
1381
        gen_op_mov_TN_reg[ot][0][d]();
1382
    else
1383
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1384
    if (s1->cc_op != CC_OP_DYNAMIC)
1385
        gen_op_set_cc_op(s1->cc_op);
1386
    if (c > 0) {
1387
        gen_op_incl_T0();
1388
        s1->cc_op = CC_OP_INCB + ot;
1389
    } else {
1390
        gen_op_decl_T0();
1391
        s1->cc_op = CC_OP_DECB + ot;
1392
    }
1393
    if (d != OR_TMP0)
1394
        gen_op_mov_reg_T0[ot][d]();
1395
    else
1396
        gen_op_st_T0_A0[ot + s1->mem_index]();
1397
    gen_op_update_inc_cc();
1398
}
1399

    
1400
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1401
{
1402
    if (d != OR_TMP0)
1403
        gen_op_mov_TN_reg[ot][0][d]();
1404
    else
1405
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1406
    if (s != OR_TMP1)
1407
        gen_op_mov_TN_reg[ot][1][s]();
1408
    /* for zero counts, flags are not updated, so must do it dynamically */
1409
    if (s1->cc_op != CC_OP_DYNAMIC)
1410
        gen_op_set_cc_op(s1->cc_op);
1411

    
1412
    if (d != OR_TMP0)
1413
        gen_op_shift_T0_T1_cc[ot][op]();
1414
    else
1415
        gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
1416
    if (d != OR_TMP0)
1417
        gen_op_mov_reg_T0[ot][d]();
1418
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1419
}
1420

    
1421
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1422
{
1423
    /* currently not optimized */
1424
    gen_op_movl_T1_im(c);
1425
    gen_shift(s1, op, ot, d, OR_TMP1);
1426
}
1427

    
1428
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1429
{
1430
    target_long disp;
1431
    int havesib;
1432
    int base;
1433
    int index;
1434
    int scale;
1435
    int opreg;
1436
    int mod, rm, code, override, must_add_seg;
1437

    
1438
    override = s->override;
1439
    must_add_seg = s->addseg;
1440
    if (override >= 0)
1441
        must_add_seg = 1;
1442
    mod = (modrm >> 6) & 3;
1443
    rm = modrm & 7;
1444

    
1445
    if (s->aflag) {
1446

    
1447
        havesib = 0;
1448
        base = rm;
1449
        index = 0;
1450
        scale = 0;
1451

    
1452
        if (base == 4) {
1453
            havesib = 1;
1454
            code = ldub_code(s->pc++);
1455
            scale = (code >> 6) & 3;
1456
            index = ((code >> 3) & 7) | REX_X(s);
1457
            base = (code & 7);
1458
        }
1459
        base |= REX_B(s);
1460

    
1461
        switch (mod) {
1462
        case 0:
1463
            if ((base & 7) == 5) {
1464
                base = -1;
1465
                disp = (int32_t)ldl_code(s->pc);
1466
                s->pc += 4;
1467
                if (CODE64(s) && !havesib) {
1468
                    disp += s->pc + s->rip_offset;
1469
                }
1470
            } else {
1471
                disp = 0;
1472
            }
1473
            break;
1474
        case 1:
1475
            disp = (int8_t)ldub_code(s->pc++);
1476
            break;
1477
        default:
1478
        case 2:
1479
            disp = ldl_code(s->pc);
1480
            s->pc += 4;
1481
            break;
1482
        }
1483

    
1484
        if (base >= 0) {
1485
            /* for correct popl handling with esp */
1486
            if (base == 4 && s->popl_esp_hack)
1487
                disp += s->popl_esp_hack;
1488
#ifdef TARGET_X86_64
1489
            if (s->aflag == 2) {
1490
                gen_op_movq_A0_reg[base]();
1491
                if (disp != 0) {
1492
                    if ((int32_t)disp == disp)
1493
                        gen_op_addq_A0_im(disp);
1494
                    else
1495
                        gen_op_addq_A0_im64(disp >> 32, disp);
1496
                }
1497
            } else
1498
#endif
1499
            {
1500
                gen_op_movl_A0_reg[base]();
1501
                if (disp != 0)
1502
                    gen_op_addl_A0_im(disp);
1503
            }
1504
        } else {
1505
#ifdef TARGET_X86_64
1506
            if (s->aflag == 2) {
1507
                if ((int32_t)disp == disp)
1508
                    gen_op_movq_A0_im(disp);
1509
                else
1510
                    gen_op_movq_A0_im64(disp >> 32, disp);
1511
            } else
1512
#endif
1513
            {
1514
                gen_op_movl_A0_im(disp);
1515
            }
1516
        }
1517
        /* XXX: index == 4 is always invalid */
1518
        if (havesib && (index != 4 || scale != 0)) {
1519
#ifdef TARGET_X86_64
1520
            if (s->aflag == 2) {
1521
                gen_op_addq_A0_reg_sN[scale][index]();
1522
            } else
1523
#endif
1524
            {
1525
                gen_op_addl_A0_reg_sN[scale][index]();
1526
            }
1527
        }
1528
        if (must_add_seg) {
1529
            if (override < 0) {
1530
                if (base == R_EBP || base == R_ESP)
1531
                    override = R_SS;
1532
                else
1533
                    override = R_DS;
1534
            }
1535
#ifdef TARGET_X86_64
1536
            if (s->aflag == 2) {
1537
                gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1538
            } else
1539
#endif
1540
            {
1541
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1542
            }
1543
        }
1544
    } else {
1545
        switch (mod) {
1546
        case 0:
1547
            if (rm == 6) {
1548
                disp = lduw_code(s->pc);
1549
                s->pc += 2;
1550
                gen_op_movl_A0_im(disp);
1551
                rm = 0; /* avoid SS override */
1552
                goto no_rm;
1553
            } else {
1554
                disp = 0;
1555
            }
1556
            break;
1557
        case 1:
1558
            disp = (int8_t)ldub_code(s->pc++);
1559
            break;
1560
        default:
1561
        case 2:
1562
            disp = lduw_code(s->pc);
1563
            s->pc += 2;
1564
            break;
1565
        }
1566
        switch(rm) {
1567
        case 0:
1568
            gen_op_movl_A0_reg[R_EBX]();
1569
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1570
            break;
1571
        case 1:
1572
            gen_op_movl_A0_reg[R_EBX]();
1573
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1574
            break;
1575
        case 2:
1576
            gen_op_movl_A0_reg[R_EBP]();
1577
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1578
            break;
1579
        case 3:
1580
            gen_op_movl_A0_reg[R_EBP]();
1581
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1582
            break;
1583
        case 4:
1584
            gen_op_movl_A0_reg[R_ESI]();
1585
            break;
1586
        case 5:
1587
            gen_op_movl_A0_reg[R_EDI]();
1588
            break;
1589
        case 6:
1590
            gen_op_movl_A0_reg[R_EBP]();
1591
            break;
1592
        default:
1593
        case 7:
1594
            gen_op_movl_A0_reg[R_EBX]();
1595
            break;
1596
        }
1597
        if (disp != 0)
1598
            gen_op_addl_A0_im(disp);
1599
        gen_op_andl_A0_ffff();
1600
    no_rm:
1601
        if (must_add_seg) {
1602
            if (override < 0) {
1603
                if (rm == 2 || rm == 3 || rm == 6)
1604
                    override = R_SS;
1605
                else
1606
                    override = R_DS;
1607
            }
1608
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1609
        }
1610
    }
1611

    
1612
    opreg = OR_A0;
1613
    disp = 0;
1614
    *reg_ptr = opreg;
1615
    *offset_ptr = disp;
1616
}
1617

    
1618
static void gen_nop_modrm(DisasContext *s, int modrm)
1619
{
1620
    int mod, rm, base, code;
1621

    
1622
    mod = (modrm >> 6) & 3;
1623
    if (mod == 3)
1624
        return;
1625
    rm = modrm & 7;
1626

    
1627
    if (s->aflag) {
1628

    
1629
        base = rm;
1630

    
1631
        if (base == 4) {
1632
            code = ldub_code(s->pc++);
1633
            base = (code & 7);
1634
        }
1635

    
1636
        switch (mod) {
1637
        case 0:
1638
            if (base == 5) {
1639
                s->pc += 4;
1640
            }
1641
            break;
1642
        case 1:
1643
            s->pc++;
1644
            break;
1645
        default:
1646
        case 2:
1647
            s->pc += 4;
1648
            break;
1649
        }
1650
    } else {
1651
        switch (mod) {
1652
        case 0:
1653
            if (rm == 6) {
1654
                s->pc += 2;
1655
            }
1656
            break;
1657
        case 1:
1658
            s->pc++;
1659
            break;
1660
        default:
1661
        case 2:
1662
            s->pc += 2;
1663
            break;
1664
        }
1665
    }
1666
}
1667

    
1668
/* used for LEA and MOV AX, mem */
1669
static void gen_add_A0_ds_seg(DisasContext *s)
1670
{
1671
    int override, must_add_seg;
1672
    must_add_seg = s->addseg;
1673
    override = R_DS;
1674
    if (s->override >= 0) {
1675
        override = s->override;
1676
        must_add_seg = 1;
1677
    } else {
1678
        override = R_DS;
1679
    }
1680
    if (must_add_seg) {
1681
#ifdef TARGET_X86_64
1682
        if (CODE64(s)) {
1683
            gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1684
        } else
1685
#endif
1686
        {
1687
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1688
        }
1689
    }
1690
}
1691

    
1692
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1693
   OR_TMP0 */
1694
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1695
{
1696
    int mod, rm, opreg, disp;
1697

    
1698
    mod = (modrm >> 6) & 3;
1699
    rm = (modrm & 7) | REX_B(s);
1700
    if (mod == 3) {
1701
        if (is_store) {
1702
            if (reg != OR_TMP0)
1703
                gen_op_mov_TN_reg[ot][0][reg]();
1704
            gen_op_mov_reg_T0[ot][rm]();
1705
        } else {
1706
            gen_op_mov_TN_reg[ot][0][rm]();
1707
            if (reg != OR_TMP0)
1708
                gen_op_mov_reg_T0[ot][reg]();
1709
        }
1710
    } else {
1711
        gen_lea_modrm(s, modrm, &opreg, &disp);
1712
        if (is_store) {
1713
            if (reg != OR_TMP0)
1714
                gen_op_mov_TN_reg[ot][0][reg]();
1715
            gen_op_st_T0_A0[ot + s->mem_index]();
1716
        } else {
1717
            gen_op_ld_T0_A0[ot + s->mem_index]();
1718
            if (reg != OR_TMP0)
1719
                gen_op_mov_reg_T0[ot][reg]();
1720
        }
1721
    }
1722
}
1723

    
1724
static inline uint32_t insn_get(DisasContext *s, int ot)
1725
{
1726
    uint32_t ret;
1727

    
1728
    switch(ot) {
1729
    case OT_BYTE:
1730
        ret = ldub_code(s->pc);
1731
        s->pc++;
1732
        break;
1733
    case OT_WORD:
1734
        ret = lduw_code(s->pc);
1735
        s->pc += 2;
1736
        break;
1737
    default:
1738
    case OT_LONG:
1739
        ret = ldl_code(s->pc);
1740
        s->pc += 4;
1741
        break;
1742
    }
1743
    return ret;
1744
}
1745

    
1746
static inline int insn_const_size(unsigned int ot)
1747
{
1748
    if (ot <= OT_LONG)
1749
        return 1 << ot;
1750
    else
1751
        return 4;
1752
}
1753

    
1754
static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
1755
{
1756
    TranslationBlock *tb;
1757
    target_ulong pc;
1758

    
1759
    pc = s->cs_base + eip;
1760
    tb = s->tb;
1761
    /* NOTE: we handle the case where the TB spans two pages here */
1762
    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
1763
        (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))  {
1764
        /* jump to same page: we can use a direct jump */
1765
        if (tb_num == 0)
1766
            gen_op_goto_tb0(TBPARAM(tb));
1767
        else
1768
            gen_op_goto_tb1(TBPARAM(tb));
1769
        gen_jmp_im(eip);
1770
        gen_op_movl_T0_im((long)tb + tb_num);
1771
        gen_op_exit_tb();
1772
    } else {
1773
        /* jump to another page: currently not optimized */
1774
        gen_jmp_im(eip);
1775
        gen_eob(s);
1776
    }
1777
}
1778

    
1779
static inline void gen_jcc(DisasContext *s, int b,
1780
                           target_ulong val, target_ulong next_eip)
1781
{
1782
    TranslationBlock *tb;
1783
    int inv, jcc_op;
1784
    GenOpFunc1 *func;
1785
    target_ulong tmp;
1786
    int l1, l2;
1787

    
1788
    inv = b & 1;
1789
    jcc_op = (b >> 1) & 7;
1790

    
1791
    if (s->jmp_opt) {
1792
        switch(s->cc_op) {
1793
            /* we optimize the cmp/jcc case */
1794
        case CC_OP_SUBB:
1795
        case CC_OP_SUBW:
1796
        case CC_OP_SUBL:
1797
        case CC_OP_SUBQ:
1798
            func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1799
            break;
1800

    
1801
            /* some jumps are easy to compute */
1802
        case CC_OP_ADDB:
1803
        case CC_OP_ADDW:
1804
        case CC_OP_ADDL:
1805
        case CC_OP_ADDQ:
1806

    
1807
        case CC_OP_ADCB:
1808
        case CC_OP_ADCW:
1809
        case CC_OP_ADCL:
1810
        case CC_OP_ADCQ:
1811

    
1812
        case CC_OP_SBBB:
1813
        case CC_OP_SBBW:
1814
        case CC_OP_SBBL:
1815
        case CC_OP_SBBQ:
1816

    
1817
        case CC_OP_LOGICB:
1818
        case CC_OP_LOGICW:
1819
        case CC_OP_LOGICL:
1820
        case CC_OP_LOGICQ:
1821

    
1822
        case CC_OP_INCB:
1823
        case CC_OP_INCW:
1824
        case CC_OP_INCL:
1825
        case CC_OP_INCQ:
1826

    
1827
        case CC_OP_DECB:
1828
        case CC_OP_DECW:
1829
        case CC_OP_DECL:
1830
        case CC_OP_DECQ:
1831

    
1832
        case CC_OP_SHLB:
1833
        case CC_OP_SHLW:
1834
        case CC_OP_SHLL:
1835
        case CC_OP_SHLQ:
1836

    
1837
        case CC_OP_SARB:
1838
        case CC_OP_SARW:
1839
        case CC_OP_SARL:
1840
        case CC_OP_SARQ:
1841
            switch(jcc_op) {
1842
            case JCC_Z:
1843
                func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1844
                break;
1845
            case JCC_S:
1846
                func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1847
                break;
1848
            default:
1849
                func = NULL;
1850
                break;
1851
            }
1852
            break;
1853
        default:
1854
            func = NULL;
1855
            break;
1856
        }
1857

    
1858
        if (s->cc_op != CC_OP_DYNAMIC) {
1859
            gen_op_set_cc_op(s->cc_op);
1860
            s->cc_op = CC_OP_DYNAMIC;
1861
        }
1862

    
1863
        if (!func) {
1864
            gen_setcc_slow[jcc_op]();
1865
            func = gen_op_jnz_T0_label;
1866
        }
1867

    
1868
        if (inv) {
1869
            tmp = val;
1870
            val = next_eip;
1871
            next_eip = tmp;
1872
        }
1873
        tb = s->tb;
1874

    
1875
        l1 = gen_new_label();
1876
        func(l1);
1877

    
1878
        gen_goto_tb(s, 0, next_eip);
1879

    
1880
        gen_set_label(l1);
1881
        gen_goto_tb(s, 1, val);
1882

    
1883
        s->is_jmp = 3;
1884
    } else {
1885

    
1886
        if (s->cc_op != CC_OP_DYNAMIC) {
1887
            gen_op_set_cc_op(s->cc_op);
1888
            s->cc_op = CC_OP_DYNAMIC;
1889
        }
1890
        gen_setcc_slow[jcc_op]();
1891
        if (inv) {
1892
            tmp = val;
1893
            val = next_eip;
1894
            next_eip = tmp;
1895
        }
1896
        l1 = gen_new_label();
1897
        l2 = gen_new_label();
1898
        gen_op_jnz_T0_label(l1);
1899
        gen_jmp_im(next_eip);
1900
        gen_op_jmp_label(l2);
1901
        gen_set_label(l1);
1902
        gen_jmp_im(val);
1903
        gen_set_label(l2);
1904
        gen_eob(s);
1905
    }
1906
}
1907

    
1908
static void gen_setcc(DisasContext *s, int b)
1909
{
1910
    int inv, jcc_op;
1911
    GenOpFunc *func;
1912

    
1913
    inv = b & 1;
1914
    jcc_op = (b >> 1) & 7;
1915
    switch(s->cc_op) {
1916
        /* we optimize the cmp/jcc case */
1917
    case CC_OP_SUBB:
1918
    case CC_OP_SUBW:
1919
    case CC_OP_SUBL:
1920
    case CC_OP_SUBQ:
1921
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1922
        if (!func)
1923
            goto slow_jcc;
1924
        break;
1925

    
1926
        /* some jumps are easy to compute */
1927
    case CC_OP_ADDB:
1928
    case CC_OP_ADDW:
1929
    case CC_OP_ADDL:
1930
    case CC_OP_ADDQ:
1931

    
1932
    case CC_OP_LOGICB:
1933
    case CC_OP_LOGICW:
1934
    case CC_OP_LOGICL:
1935
    case CC_OP_LOGICQ:
1936

    
1937
    case CC_OP_INCB:
1938
    case CC_OP_INCW:
1939
    case CC_OP_INCL:
1940
    case CC_OP_INCQ:
1941

    
1942
    case CC_OP_DECB:
1943
    case CC_OP_DECW:
1944
    case CC_OP_DECL:
1945
    case CC_OP_DECQ:
1946

    
1947
    case CC_OP_SHLB:
1948
    case CC_OP_SHLW:
1949
    case CC_OP_SHLL:
1950
    case CC_OP_SHLQ:
1951
        switch(jcc_op) {
1952
        case JCC_Z:
1953
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1954
            break;
1955
        case JCC_S:
1956
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1957
            break;
1958
        default:
1959
            goto slow_jcc;
1960
        }
1961
        break;
1962
    default:
1963
    slow_jcc:
1964
        if (s->cc_op != CC_OP_DYNAMIC)
1965
            gen_op_set_cc_op(s->cc_op);
1966
        func = gen_setcc_slow[jcc_op];
1967
        break;
1968
    }
1969
    func();
1970
    if (inv) {
1971
        gen_op_xor_T0_1();
1972
    }
1973
}
1974

    
1975
/* move T0 to seg_reg and compute if the CPU state may change. Never
1976
   call this function with seg_reg == R_CS */
1977
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
1978
{
1979
    if (s->pe && !s->vm86) {
1980
        /* XXX: optimize by finding processor state dynamically */
1981
        if (s->cc_op != CC_OP_DYNAMIC)
1982
            gen_op_set_cc_op(s->cc_op);
1983
        gen_jmp_im(cur_eip);
1984
        gen_op_movl_seg_T0(seg_reg);
1985
        /* abort translation because the addseg value may change or
1986
           because ss32 may change. For R_SS, translation must always
1987
           stop as a special handling must be done to disable hardware
1988
           interrupts for the next instruction */
1989
        if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1990
            s->is_jmp = 3;
1991
    } else {
1992
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1993
        if (seg_reg == R_SS)
1994
            s->is_jmp = 3;
1995
    }
1996
}
1997

    
1998
#ifdef TARGET_X86_64
1999
#define SVM_movq_T1_im(x) gen_op_movq_T1_im64((x) >> 32, x)
2000
#else
2001
#define SVM_movq_T1_im(x) gen_op_movl_T1_im(x)
2002
#endif
2003

    
2004
static inline int
2005
gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
2006
{
2007
#if !defined(CONFIG_USER_ONLY)
2008
    if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
2009
        if (s->cc_op != CC_OP_DYNAMIC)
2010
            gen_op_set_cc_op(s->cc_op);
2011
        SVM_movq_T1_im(s->pc - s->cs_base);
2012
        gen_jmp_im(pc_start - s->cs_base);
2013
        gen_op_geneflags();
2014
        gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
2015
        s->cc_op = CC_OP_DYNAMIC;
2016
        /* FIXME: maybe we could move the io intercept vector to the TB as well
2017
                  so we know if this is an EOB or not ... let's assume it's not
2018
                  for now. */
2019
    }
2020
#endif
2021
    return 0;
2022
}
2023

    
2024
static inline int svm_is_rep(int prefixes)
2025
{
2026
    return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2027
}
2028

    
2029
static inline int
2030
gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
2031
                              uint64_t type, uint64_t param)
2032
{
2033
    if(!(s->flags & (INTERCEPT_SVM_MASK)))
2034
        /* no SVM activated */
2035
        return 0;
2036
    switch(type) {
2037
        /* CRx and DRx reads/writes */
2038
        case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
2039
            if (s->cc_op != CC_OP_DYNAMIC) {
2040
                gen_op_set_cc_op(s->cc_op);
2041
                s->cc_op = CC_OP_DYNAMIC;
2042
            }
2043
            gen_jmp_im(pc_start - s->cs_base);
2044
            SVM_movq_T1_im(param);
2045
            gen_op_geneflags();
2046
            gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2047
            /* this is a special case as we do not know if the interception occurs
2048
               so we assume there was none */
2049
            return 0;
2050
        case SVM_EXIT_MSR:
2051
            if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
2052
                if (s->cc_op != CC_OP_DYNAMIC) {
2053
                    gen_op_set_cc_op(s->cc_op);
2054
                    s->cc_op = CC_OP_DYNAMIC;
2055
                }
2056
                gen_jmp_im(pc_start - s->cs_base);
2057
                SVM_movq_T1_im(param);
2058
                gen_op_geneflags();
2059
                gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
2060
                /* this is a special case as we do not know if the interception occurs
2061
                   so we assume there was none */
2062
                return 0;
2063
            }
2064
            break;
2065
        default:
2066
            if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) {
2067
                if (s->cc_op != CC_OP_DYNAMIC) {
2068
                    gen_op_set_cc_op(s->cc_op);
2069
                    s->cc_op = CC_OP_EFLAGS;
2070
                }
2071
                gen_jmp_im(pc_start - s->cs_base);
2072
                SVM_movq_T1_im(param);
2073
                gen_op_geneflags();
2074
                gen_op_svm_vmexit(type >> 32, type);
2075
                /* we can optimize this one so TBs don't get longer
2076
                   than up to vmexit */
2077
                gen_eob(s);
2078
                return 1;
2079
            }
2080
    }
2081
    return 0;
2082
}
2083

    
2084
static inline int
2085
gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2086
{
2087
    return gen_svm_check_intercept_param(s, pc_start, type, 0);
2088
}
2089

    
2090
static inline void gen_stack_update(DisasContext *s, int addend)
2091
{
2092
#ifdef TARGET_X86_64
2093
    if (CODE64(s)) {
2094
        if (addend == 8)
2095
            gen_op_addq_ESP_8();
2096
        else
2097
            gen_op_addq_ESP_im(addend);
2098
    } else
2099
#endif
2100
    if (s->ss32) {
2101
        if (addend == 2)
2102
            gen_op_addl_ESP_2();
2103
        else if (addend == 4)
2104
            gen_op_addl_ESP_4();
2105
        else
2106
            gen_op_addl_ESP_im(addend);
2107
    } else {
2108
        if (addend == 2)
2109
            gen_op_addw_ESP_2();
2110
        else if (addend == 4)
2111
            gen_op_addw_ESP_4();
2112
        else
2113
            gen_op_addw_ESP_im(addend);
2114
    }
2115
}
2116

    
2117
/* generate a push. It depends on ss32, addseg and dflag */
2118
static void gen_push_T0(DisasContext *s)
2119
{
2120
#ifdef TARGET_X86_64
2121
    if (CODE64(s)) {
2122
        gen_op_movq_A0_reg[R_ESP]();
2123
        if (s->dflag) {
2124
            gen_op_subq_A0_8();
2125
            gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
2126
        } else {
2127
            gen_op_subq_A0_2();
2128
            gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2129
        }
2130
        gen_op_movq_ESP_A0();
2131
    } else
2132
#endif
2133
    {
2134
        gen_op_movl_A0_reg[R_ESP]();
2135
        if (!s->dflag)
2136
            gen_op_subl_A0_2();
2137
        else
2138
            gen_op_subl_A0_4();
2139
        if (s->ss32) {
2140
            if (s->addseg) {
2141
                gen_op_movl_T1_A0();
2142
                gen_op_addl_A0_SS();
2143
            }
2144
        } else {
2145
            gen_op_andl_A0_ffff();
2146
            gen_op_movl_T1_A0();
2147
            gen_op_addl_A0_SS();
2148
        }
2149
        gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
2150
        if (s->ss32 && !s->addseg)
2151
            gen_op_movl_ESP_A0();
2152
        else
2153
            gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2154
    }
2155
}
2156

    
2157
/* generate a push. It depends on ss32, addseg and dflag */
2158
/* slower version for T1, only used for call Ev */
2159
static void gen_push_T1(DisasContext *s)
2160
{
2161
#ifdef TARGET_X86_64
2162
    if (CODE64(s)) {
2163
        gen_op_movq_A0_reg[R_ESP]();
2164
        if (s->dflag) {
2165
            gen_op_subq_A0_8();
2166
            gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2167
        } else {
2168
            gen_op_subq_A0_2();
2169
            gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2170
        }
2171
        gen_op_movq_ESP_A0();
2172
    } else
2173
#endif
2174
    {
2175
        gen_op_movl_A0_reg[R_ESP]();
2176
        if (!s->dflag)
2177
            gen_op_subl_A0_2();
2178
        else
2179
            gen_op_subl_A0_4();
2180
        if (s->ss32) {
2181
            if (s->addseg) {
2182
                gen_op_addl_A0_SS();
2183
            }
2184
        } else {
2185
            gen_op_andl_A0_ffff();
2186
            gen_op_addl_A0_SS();
2187
        }
2188
        gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
2189

    
2190
        if (s->ss32 && !s->addseg)
2191
            gen_op_movl_ESP_A0();
2192
        else
2193
            gen_stack_update(s, (-2) << s->dflag);
2194
    }
2195
}
2196

    
2197
/* two step pop is necessary for precise exceptions */
2198
static void gen_pop_T0(DisasContext *s)
2199
{
2200
#ifdef TARGET_X86_64
2201
    if (CODE64(s)) {
2202
        gen_op_movq_A0_reg[R_ESP]();
2203
        gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
2204
    } else
2205
#endif
2206
    {
2207
        gen_op_movl_A0_reg[R_ESP]();
2208
        if (s->ss32) {
2209
            if (s->addseg)
2210
                gen_op_addl_A0_SS();
2211
        } else {
2212
            gen_op_andl_A0_ffff();
2213
            gen_op_addl_A0_SS();
2214
        }
2215
        gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2216
    }
2217
}
2218

    
2219
static void gen_pop_update(DisasContext *s)
2220
{
2221
#ifdef TARGET_X86_64
2222
    if (CODE64(s) && s->dflag) {
2223
        gen_stack_update(s, 8);
2224
    } else
2225
#endif
2226
    {
2227
        gen_stack_update(s, 2 << s->dflag);
2228
    }
2229
}
2230

    
2231
static void gen_stack_A0(DisasContext *s)
2232
{
2233
    gen_op_movl_A0_ESP();
2234
    if (!s->ss32)
2235
        gen_op_andl_A0_ffff();
2236
    gen_op_movl_T1_A0();
2237
    if (s->addseg)
2238
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2239
}
2240

    
2241
/* NOTE: wrap around in 16 bit not fully handled */
2242
static void gen_pusha(DisasContext *s)
2243
{
2244
    int i;
2245
    gen_op_movl_A0_ESP();
2246
    gen_op_addl_A0_im(-16 <<  s->dflag);
2247
    if (!s->ss32)
2248
        gen_op_andl_A0_ffff();
2249
    gen_op_movl_T1_A0();
2250
    if (s->addseg)
2251
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2252
    for(i = 0;i < 8; i++) {
2253
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2254
        gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2255
        gen_op_addl_A0_im(2 <<  s->dflag);
2256
    }
2257
    gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2258
}
2259

    
2260
/* NOTE: wrap around in 16 bit not fully handled */
2261
static void gen_popa(DisasContext *s)
2262
{
2263
    int i;
2264
    gen_op_movl_A0_ESP();
2265
    if (!s->ss32)
2266
        gen_op_andl_A0_ffff();
2267
    gen_op_movl_T1_A0();
2268
    gen_op_addl_T1_im(16 <<  s->dflag);
2269
    if (s->addseg)
2270
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2271
    for(i = 0;i < 8; i++) {
2272
        /* ESP is not reloaded */
2273
        if (i != 3) {
2274
            gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2275
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2276
        }
2277
        gen_op_addl_A0_im(2 <<  s->dflag);
2278
    }
2279
    gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2280
}
2281

    
2282
static void gen_enter(DisasContext *s, int esp_addend, int level)
2283
{
2284
    int ot, opsize;
2285

    
2286
    level &= 0x1f;
2287
#ifdef TARGET_X86_64
2288
    if (CODE64(s)) {
2289
        ot = s->dflag ? OT_QUAD : OT_WORD;
2290
        opsize = 1 << ot;
2291

    
2292
        gen_op_movl_A0_ESP();
2293
        gen_op_addq_A0_im(-opsize);
2294
        gen_op_movl_T1_A0();
2295

    
2296
        /* push bp */
2297
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2298
        gen_op_st_T0_A0[ot + s->mem_index]();
2299
        if (level) {
2300
            gen_op_enter64_level(level, (ot == OT_QUAD));
2301
        }
2302
        gen_op_mov_reg_T1[ot][R_EBP]();
2303
        gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2304
        gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
2305
    } else
2306
#endif
2307
    {
2308
        ot = s->dflag + OT_WORD;
2309
        opsize = 2 << s->dflag;
2310

    
2311
        gen_op_movl_A0_ESP();
2312
        gen_op_addl_A0_im(-opsize);
2313
        if (!s->ss32)
2314
            gen_op_andl_A0_ffff();
2315
        gen_op_movl_T1_A0();
2316
        if (s->addseg)
2317
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2318
        /* push bp */
2319
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2320
        gen_op_st_T0_A0[ot + s->mem_index]();
2321
        if (level) {
2322
            gen_op_enter_level(level, s->dflag);
2323
        }
2324
        gen_op_mov_reg_T1[ot][R_EBP]();
2325
        gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2326
        gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2327
    }
2328
}
2329

    
2330
static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2331
{
2332
    if (s->cc_op != CC_OP_DYNAMIC)
2333
        gen_op_set_cc_op(s->cc_op);
2334
    gen_jmp_im(cur_eip);
2335
    gen_op_raise_exception(trapno);
2336
    s->is_jmp = 3;
2337
}
2338

    
2339
/* an interrupt is different from an exception because of the
2340
   privilege checks */
2341
static void gen_interrupt(DisasContext *s, int intno,
2342
                          target_ulong cur_eip, target_ulong next_eip)
2343
{
2344
    if (s->cc_op != CC_OP_DYNAMIC)
2345
        gen_op_set_cc_op(s->cc_op);
2346
    gen_jmp_im(cur_eip);
2347
    gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2348
    s->is_jmp = 3;
2349
}
2350

    
2351
static void gen_debug(DisasContext *s, target_ulong cur_eip)
2352
{
2353
    if (s->cc_op != CC_OP_DYNAMIC)
2354
        gen_op_set_cc_op(s->cc_op);
2355
    gen_jmp_im(cur_eip);
2356
    gen_op_debug();
2357
    s->is_jmp = 3;
2358
}
2359

    
2360
/* generate a generic end of block. Trace exception is also generated
2361
   if needed */
2362
static void gen_eob(DisasContext *s)
2363
{
2364
    if (s->cc_op != CC_OP_DYNAMIC)
2365
        gen_op_set_cc_op(s->cc_op);
2366
    if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2367
        gen_op_reset_inhibit_irq();
2368
    }
2369
    if (s->singlestep_enabled) {
2370
        gen_op_debug();
2371
    } else if (s->tf) {
2372
        gen_op_single_step();
2373
    } else {
2374
        gen_op_movl_T0_0();
2375
        gen_op_exit_tb();
2376
    }
2377
    s->is_jmp = 3;
2378
}
2379

    
2380
/* generate a jump to eip. No segment change must happen before as a
2381
   direct call to the next block may occur */
2382
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2383
{
2384
    if (s->jmp_opt) {
2385
        if (s->cc_op != CC_OP_DYNAMIC) {
2386
            gen_op_set_cc_op(s->cc_op);
2387
            s->cc_op = CC_OP_DYNAMIC;
2388
        }
2389
        gen_goto_tb(s, tb_num, eip);
2390
        s->is_jmp = 3;
2391
    } else {
2392
        gen_jmp_im(eip);
2393
        gen_eob(s);
2394
    }
2395
}
2396

    
2397
static void gen_jmp(DisasContext *s, target_ulong eip)
2398
{
2399
    gen_jmp_tb(s, eip, 0);
2400
}
2401

    
2402
static void gen_movtl_T0_im(target_ulong val)
2403
{
2404
#ifdef TARGET_X86_64
2405
    if ((int32_t)val == val) {
2406
        gen_op_movl_T0_im(val);
2407
    } else {
2408
        gen_op_movq_T0_im64(val >> 32, val);
2409
    }
2410
#else
2411
    gen_op_movl_T0_im(val);
2412
#endif
2413
}
2414

    
2415
static void gen_movtl_T1_im(target_ulong val)
2416
{
2417
#ifdef TARGET_X86_64
2418
    if ((int32_t)val == val) {
2419
        gen_op_movl_T1_im(val);
2420
    } else {
2421
        gen_op_movq_T1_im64(val >> 32, val);
2422
    }
2423
#else
2424
    gen_op_movl_T1_im(val);
2425
#endif
2426
}
2427

    
2428
static void gen_add_A0_im(DisasContext *s, int val)
2429
{
2430
#ifdef TARGET_X86_64
2431
    if (CODE64(s))
2432
        gen_op_addq_A0_im(val);
2433
    else
2434
#endif
2435
        gen_op_addl_A0_im(val);
2436
}
2437

    
2438
static GenOpFunc1 *gen_ldq_env_A0[3] = {
2439
    gen_op_ldq_raw_env_A0,
2440
#ifndef CONFIG_USER_ONLY
2441
    gen_op_ldq_kernel_env_A0,
2442
    gen_op_ldq_user_env_A0,
2443
#endif
2444
};
2445

    
2446
static GenOpFunc1 *gen_stq_env_A0[3] = {
2447
    gen_op_stq_raw_env_A0,
2448
#ifndef CONFIG_USER_ONLY
2449
    gen_op_stq_kernel_env_A0,
2450
    gen_op_stq_user_env_A0,
2451
#endif
2452
};
2453

    
2454
static GenOpFunc1 *gen_ldo_env_A0[3] = {
2455
    gen_op_ldo_raw_env_A0,
2456
#ifndef CONFIG_USER_ONLY
2457
    gen_op_ldo_kernel_env_A0,
2458
    gen_op_ldo_user_env_A0,
2459
#endif
2460
};
2461

    
2462
static GenOpFunc1 *gen_sto_env_A0[3] = {
2463
    gen_op_sto_raw_env_A0,
2464
#ifndef CONFIG_USER_ONLY
2465
    gen_op_sto_kernel_env_A0,
2466
    gen_op_sto_user_env_A0,
2467
#endif
2468
};
2469

    
2470
#define SSE_SPECIAL ((GenOpFunc2 *)1)
2471

    
2472
#define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2473
#define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2474
                     gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2475

    
2476
static GenOpFunc2 *sse_op_table1[256][4] = {
2477
    /* pure SSE operations */
2478
    [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2479
    [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2480
    [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
2481
    [0x13] = { SSE_SPECIAL, SSE_SPECIAL },  /* movlps, movlpd */
2482
    [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2483
    [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2484
    [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd, movshdup */
2485
    [0x17] = { SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd */
2486

    
2487
    [0x28] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
2488
    [0x29] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
2489
    [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2490
    [0x2b] = { SSE_SPECIAL, SSE_SPECIAL },  /* movntps, movntpd */
2491
    [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2492
    [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2493
    [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2494
    [0x2f] = { gen_op_comiss, gen_op_comisd },
2495
    [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2496
    [0x51] = SSE_FOP(sqrt),
2497
    [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2498
    [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2499
    [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2500
    [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2501
    [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2502
    [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2503
    [0x58] = SSE_FOP(add),
2504
    [0x59] = SSE_FOP(mul),
2505
    [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps,
2506
               gen_op_cvtss2sd, gen_op_cvtsd2ss },
2507
    [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2508
    [0x5c] = SSE_FOP(sub),
2509
    [0x5d] = SSE_FOP(min),
2510
    [0x5e] = SSE_FOP(div),
2511
    [0x5f] = SSE_FOP(max),
2512

    
2513
    [0xc2] = SSE_FOP(cmpeq),
2514
    [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
2515

    
2516
    /* MMX ops and their SSE extensions */
2517
    [0x60] = MMX_OP2(punpcklbw),
2518
    [0x61] = MMX_OP2(punpcklwd),
2519
    [0x62] = MMX_OP2(punpckldq),
2520
    [0x63] = MMX_OP2(packsswb),
2521
    [0x64] = MMX_OP2(pcmpgtb),
2522
    [0x65] = MMX_OP2(pcmpgtw),
2523
    [0x66] = MMX_OP2(pcmpgtl),
2524
    [0x67] = MMX_OP2(packuswb),
2525
    [0x68] = MMX_OP2(punpckhbw),
2526
    [0x69] = MMX_OP2(punpckhwd),
2527
    [0x6a] = MMX_OP2(punpckhdq),
2528
    [0x6b] = MMX_OP2(packssdw),
2529
    [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2530
    [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2531
    [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2532
    [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2533
    [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx,
2534
               (GenOpFunc2 *)gen_op_pshufd_xmm,
2535
               (GenOpFunc2 *)gen_op_pshufhw_xmm,
2536
               (GenOpFunc2 *)gen_op_pshuflw_xmm },
2537
    [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2538
    [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2539
    [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2540
    [0x74] = MMX_OP2(pcmpeqb),
2541
    [0x75] = MMX_OP2(pcmpeqw),
2542
    [0x76] = MMX_OP2(pcmpeql),
2543
    [0x77] = { SSE_SPECIAL }, /* emms */
2544
    [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2545
    [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2546
    [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2547
    [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2548
    [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2549
    [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2550
    [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2551
    [0xd1] = MMX_OP2(psrlw),
2552
    [0xd2] = MMX_OP2(psrld),
2553
    [0xd3] = MMX_OP2(psrlq),
2554
    [0xd4] = MMX_OP2(paddq),
2555
    [0xd5] = MMX_OP2(pmullw),
2556
    [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2557
    [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2558
    [0xd8] = MMX_OP2(psubusb),
2559
    [0xd9] = MMX_OP2(psubusw),
2560
    [0xda] = MMX_OP2(pminub),
2561
    [0xdb] = MMX_OP2(pand),
2562
    [0xdc] = MMX_OP2(paddusb),
2563
    [0xdd] = MMX_OP2(paddusw),
2564
    [0xde] = MMX_OP2(pmaxub),
2565
    [0xdf] = MMX_OP2(pandn),
2566
    [0xe0] = MMX_OP2(pavgb),
2567
    [0xe1] = MMX_OP2(psraw),
2568
    [0xe2] = MMX_OP2(psrad),
2569
    [0xe3] = MMX_OP2(pavgw),
2570
    [0xe4] = MMX_OP2(pmulhuw),
2571
    [0xe5] = MMX_OP2(pmulhw),
2572
    [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2573
    [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
2574
    [0xe8] = MMX_OP2(psubsb),
2575
    [0xe9] = MMX_OP2(psubsw),
2576
    [0xea] = MMX_OP2(pminsw),
2577
    [0xeb] = MMX_OP2(por),
2578
    [0xec] = MMX_OP2(paddsb),
2579
    [0xed] = MMX_OP2(paddsw),
2580
    [0xee] = MMX_OP2(pmaxsw),
2581
    [0xef] = MMX_OP2(pxor),
2582
    [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
2583
    [0xf1] = MMX_OP2(psllw),
2584
    [0xf2] = MMX_OP2(pslld),
2585
    [0xf3] = MMX_OP2(psllq),
2586
    [0xf4] = MMX_OP2(pmuludq),
2587
    [0xf5] = MMX_OP2(pmaddwd),
2588
    [0xf6] = MMX_OP2(psadbw),
2589
    [0xf7] = MMX_OP2(maskmov),
2590
    [0xf8] = MMX_OP2(psubb),
2591
    [0xf9] = MMX_OP2(psubw),
2592
    [0xfa] = MMX_OP2(psubl),
2593
    [0xfb] = MMX_OP2(psubq),
2594
    [0xfc] = MMX_OP2(paddb),
2595
    [0xfd] = MMX_OP2(paddw),
2596
    [0xfe] = MMX_OP2(paddl),
2597
};
2598

    
2599
static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2600
    [0 + 2] = MMX_OP2(psrlw),
2601
    [0 + 4] = MMX_OP2(psraw),
2602
    [0 + 6] = MMX_OP2(psllw),
2603
    [8 + 2] = MMX_OP2(psrld),
2604
    [8 + 4] = MMX_OP2(psrad),
2605
    [8 + 6] = MMX_OP2(pslld),
2606
    [16 + 2] = MMX_OP2(psrlq),
2607
    [16 + 3] = { NULL, gen_op_psrldq_xmm },
2608
    [16 + 6] = MMX_OP2(psllq),
2609
    [16 + 7] = { NULL, gen_op_pslldq_xmm },
2610
};
2611

    
2612
static GenOpFunc1 *sse_op_table3[4 * 3] = {
2613
    gen_op_cvtsi2ss,
2614
    gen_op_cvtsi2sd,
2615
    X86_64_ONLY(gen_op_cvtsq2ss),
2616
    X86_64_ONLY(gen_op_cvtsq2sd),
2617

    
2618
    gen_op_cvttss2si,
2619
    gen_op_cvttsd2si,
2620
    X86_64_ONLY(gen_op_cvttss2sq),
2621
    X86_64_ONLY(gen_op_cvttsd2sq),
2622

    
2623
    gen_op_cvtss2si,
2624
    gen_op_cvtsd2si,
2625
    X86_64_ONLY(gen_op_cvtss2sq),
2626
    X86_64_ONLY(gen_op_cvtsd2sq),
2627
};
2628

    
2629
static GenOpFunc2 *sse_op_table4[8][4] = {
2630
    SSE_FOP(cmpeq),
2631
    SSE_FOP(cmplt),
2632
    SSE_FOP(cmple),
2633
    SSE_FOP(cmpunord),
2634
    SSE_FOP(cmpneq),
2635
    SSE_FOP(cmpnlt),
2636
    SSE_FOP(cmpnle),
2637
    SSE_FOP(cmpord),
2638
};
2639

    
2640
static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2641
{
2642
    int b1, op1_offset, op2_offset, is_xmm, val, ot;
2643
    int modrm, mod, rm, reg, reg_addr, offset_addr;
2644
    GenOpFunc2 *sse_op2;
2645
    GenOpFunc3 *sse_op3;
2646

    
2647
    b &= 0xff;
2648
    if (s->prefix & PREFIX_DATA)
2649
        b1 = 1;
2650
    else if (s->prefix & PREFIX_REPZ)
2651
        b1 = 2;
2652
    else if (s->prefix & PREFIX_REPNZ)
2653
        b1 = 3;
2654
    else
2655
        b1 = 0;
2656
    sse_op2 = sse_op_table1[b][b1];
2657
    if (!sse_op2)
2658
        goto illegal_op;
2659
    if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2660
        is_xmm = 1;
2661
    } else {
2662
        if (b1 == 0) {
2663
            /* MMX case */
2664
            is_xmm = 0;
2665
        } else {
2666
            is_xmm = 1;
2667
        }
2668
    }
2669
    /* simple MMX/SSE operation */
2670
    if (s->flags & HF_TS_MASK) {
2671
        gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2672
        return;
2673
    }
2674
    if (s->flags & HF_EM_MASK) {
2675
    illegal_op:
2676
        gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2677
        return;
2678
    }
2679
    if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2680
        goto illegal_op;
2681
    if (b == 0x77) {
2682
        /* emms */
2683
        gen_op_emms();
2684
        return;
2685
    }
2686
    /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2687
       the static cpu state) */
2688
    if (!is_xmm) {
2689
        gen_op_enter_mmx();
2690
    }
2691

    
2692
    modrm = ldub_code(s->pc++);
2693
    reg = ((modrm >> 3) & 7);
2694
    if (is_xmm)
2695
        reg |= rex_r;
2696
    mod = (modrm >> 6) & 3;
2697
    if (sse_op2 == SSE_SPECIAL) {
2698
        b |= (b1 << 8);
2699
        switch(b) {
2700
        case 0x0e7: /* movntq */
2701
            if (mod == 3)
2702
                goto illegal_op;
2703
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2704
            gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2705
            break;
2706
        case 0x1e7: /* movntdq */
2707
        case 0x02b: /* movntps */
2708
        case 0x12b: /* movntps */
2709
        case 0x3f0: /* lddqu */
2710
            if (mod == 3)
2711
                goto illegal_op;
2712
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2713
            gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2714
            break;
2715
        case 0x6e: /* movd mm, ea */
2716
#ifdef TARGET_X86_64
2717
            if (s->dflag == 2) {
2718
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2719
                gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2720
            } else
2721
#endif
2722
            {
2723
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2724
                gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2725
            }
2726
            break;
2727
        case 0x16e: /* movd xmm, ea */
2728
#ifdef TARGET_X86_64
2729
            if (s->dflag == 2) {
2730
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
2731
                gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2732
            } else
2733
#endif
2734
            {
2735
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2736
                gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2737
            }
2738
            break;
2739
        case 0x6f: /* movq mm, ea */
2740
            if (mod != 3) {
2741
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2742
                gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2743
            } else {
2744
                rm = (modrm & 7);
2745
                gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2746
                            offsetof(CPUX86State,fpregs[rm].mmx));
2747
            }
2748
            break;
2749
        case 0x010: /* movups */
2750
        case 0x110: /* movupd */
2751
        case 0x028: /* movaps */
2752
        case 0x128: /* movapd */
2753
        case 0x16f: /* movdqa xmm, ea */
2754
        case 0x26f: /* movdqu xmm, ea */
2755
            if (mod != 3) {
2756
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2757
                gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2758
            } else {
2759
                rm = (modrm & 7) | REX_B(s);
2760
                gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2761
                            offsetof(CPUX86State,xmm_regs[rm]));
2762
            }
2763
            break;
2764
        case 0x210: /* movss xmm, ea */
2765
            if (mod != 3) {
2766
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2767
                gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2768
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2769
                gen_op_movl_T0_0();
2770
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2771
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2772
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2773
            } else {
2774
                rm = (modrm & 7) | REX_B(s);
2775
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2776
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2777
            }
2778
            break;
2779
        case 0x310: /* movsd xmm, ea */
2780
            if (mod != 3) {
2781
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2782
                gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2783
                gen_op_movl_T0_0();
2784
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2785
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2786
            } else {
2787
                rm = (modrm & 7) | REX_B(s);
2788
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2789
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2790
            }
2791
            break;
2792
        case 0x012: /* movlps */
2793
        case 0x112: /* movlpd */
2794
            if (mod != 3) {
2795
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2796
                gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2797
            } else {
2798
                /* movhlps */
2799
                rm = (modrm & 7) | REX_B(s);
2800
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2801
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2802
            }
2803
            break;
2804
        case 0x212: /* movsldup */
2805
            if (mod != 3) {
2806
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2807
                gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2808
            } else {
2809
                rm = (modrm & 7) | REX_B(s);
2810
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2811
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2812
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2813
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
2814
            }
2815
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2816
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2817
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2818
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2819
            break;
2820
        case 0x312: /* movddup */
2821
            if (mod != 3) {
2822
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2823
                gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2824
            } else {
2825
                rm = (modrm & 7) | REX_B(s);
2826
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2827
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2828
            }
2829
            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2830
                        offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2831
            break;
2832
        case 0x016: /* movhps */
2833
        case 0x116: /* movhpd */
2834
            if (mod != 3) {
2835
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2836
                gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2837
            } else {
2838
                /* movlhps */
2839
                rm = (modrm & 7) | REX_B(s);
2840
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2841
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2842
            }
2843
            break;
2844
        case 0x216: /* movshdup */
2845
            if (mod != 3) {
2846
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2847
                gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2848
            } else {
2849
                rm = (modrm & 7) | REX_B(s);
2850
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2851
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2852
                gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2853
                            offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2854
            }
2855
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2856
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2857
            gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2858
                        offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2859
            break;
2860
        case 0x7e: /* movd ea, mm */
2861
#ifdef TARGET_X86_64
2862
            if (s->dflag == 2) {
2863
                gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2864
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
2865
            } else
2866
#endif
2867
            {
2868
                gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2869
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2870
            }
2871
            break;
2872
        case 0x17e: /* movd ea, xmm */
2873
#ifdef TARGET_X86_64
2874
            if (s->dflag == 2) {
2875
                gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2876
                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
2877
            } else
2878
#endif
2879
            {
2880
                gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2881
                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2882
            }
2883
            break;
2884
        case 0x27e: /* movq xmm, ea */
2885
            if (mod != 3) {
2886
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2887
                gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2888
            } else {
2889
                rm = (modrm & 7) | REX_B(s);
2890
                gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2891
                            offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2892
            }
2893
            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2894
            break;
2895
        case 0x7f: /* movq ea, mm */
2896
            if (mod != 3) {
2897
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2898
                gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2899
            } else {
2900
                rm = (modrm & 7);
2901
                gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2902
                            offsetof(CPUX86State,fpregs[reg].mmx));
2903
            }
2904
            break;
2905
        case 0x011: /* movups */
2906
        case 0x111: /* movupd */
2907
        case 0x029: /* movaps */
2908
        case 0x129: /* movapd */
2909
        case 0x17f: /* movdqa ea, xmm */
2910
        case 0x27f: /* movdqu ea, xmm */
2911
            if (mod != 3) {
2912
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2913
                gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2914
            } else {
2915
                rm = (modrm & 7) | REX_B(s);
2916
                gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2917
                            offsetof(CPUX86State,xmm_regs[reg]));
2918
            }
2919
            break;
2920
        case 0x211: /* movss ea, xmm */
2921
            if (mod != 3) {
2922
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2923
                gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2924
                gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2925
            } else {
2926
                rm = (modrm & 7) | REX_B(s);
2927
                gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2928
                            offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2929
            }
2930
            break;
2931
        case 0x311: /* movsd ea, xmm */
2932
            if (mod != 3) {
2933
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2934
                gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2935
            } else {
2936
                rm = (modrm & 7) | REX_B(s);
2937
                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2938
                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2939
            }
2940
            break;
2941
        case 0x013: /* movlps */
2942
        case 0x113: /* movlpd */
2943
            if (mod != 3) {
2944
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2945
                gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2946
            } else {
2947
                goto illegal_op;
2948
            }
2949
            break;
2950
        case 0x017: /* movhps */
2951
        case 0x117: /* movhpd */
2952
            if (mod != 3) {
2953
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2954
                gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2955
            } else {
2956
                goto illegal_op;
2957
            }
2958
            break;
2959
        case 0x71: /* shift mm, im */
2960
        case 0x72:
2961
        case 0x73:
2962
        case 0x171: /* shift xmm, im */
2963
        case 0x172:
2964
        case 0x173:
2965
            val = ldub_code(s->pc++);
2966
            if (is_xmm) {
2967
                gen_op_movl_T0_im(val);
2968
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2969
                gen_op_movl_T0_0();
2970
                gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2971
                op1_offset = offsetof(CPUX86State,xmm_t0);
2972
            } else {
2973
                gen_op_movl_T0_im(val);
2974
                gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2975
                gen_op_movl_T0_0();
2976
                gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2977
                op1_offset = offsetof(CPUX86State,mmx_t0);
2978
            }
2979
            sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2980
            if (!sse_op2)
2981
                goto illegal_op;
2982
            if (is_xmm) {
2983
                rm = (modrm & 7) | REX_B(s);
2984
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2985
            } else {
2986
                rm = (modrm & 7);
2987
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2988
            }
2989
            sse_op2(op2_offset, op1_offset);
2990
            break;
2991
        case 0x050: /* movmskps */
2992
            rm = (modrm & 7) | REX_B(s);
2993
            gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2994
            gen_op_mov_reg_T0[OT_LONG][reg]();
2995
            break;
2996
        case 0x150: /* movmskpd */
2997
            rm = (modrm & 7) | REX_B(s);
2998
            gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2999
            gen_op_mov_reg_T0[OT_LONG][reg]();
3000
            break;
3001
        case 0x02a: /* cvtpi2ps */
3002
        case 0x12a: /* cvtpi2pd */
3003
            gen_op_enter_mmx();
3004
            if (mod != 3) {
3005
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3006
                op2_offset = offsetof(CPUX86State,mmx_t0);
3007
                gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3008
            } else {
3009
                rm = (modrm & 7);
3010
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3011
            }
3012
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3013
            switch(b >> 8) {
3014
            case 0x0:
3015
                gen_op_cvtpi2ps(op1_offset, op2_offset);
3016
                break;
3017
            default:
3018
            case 0x1:
3019
                gen_op_cvtpi2pd(op1_offset, op2_offset);
3020
                break;
3021
            }
3022
            break;
3023
        case 0x22a: /* cvtsi2ss */
3024
        case 0x32a: /* cvtsi2sd */
3025
            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3026
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3027
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3028
            sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
3029
            break;
3030
        case 0x02c: /* cvttps2pi */
3031
        case 0x12c: /* cvttpd2pi */
3032
        case 0x02d: /* cvtps2pi */
3033
        case 0x12d: /* cvtpd2pi */
3034
            gen_op_enter_mmx();
3035
            if (mod != 3) {
3036
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3037
                op2_offset = offsetof(CPUX86State,xmm_t0);
3038
                gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3039
            } else {
3040
                rm = (modrm & 7) | REX_B(s);
3041
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3042
            }
3043
            op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
3044
            switch(b) {
3045
            case 0x02c:
3046
                gen_op_cvttps2pi(op1_offset, op2_offset);
3047
                break;
3048
            case 0x12c:
3049
                gen_op_cvttpd2pi(op1_offset, op2_offset);
3050
                break;
3051
            case 0x02d:
3052
                gen_op_cvtps2pi(op1_offset, op2_offset);
3053
                break;
3054
            case 0x12d:
3055
                gen_op_cvtpd2pi(op1_offset, op2_offset);
3056
                break;
3057
            }
3058
            break;
3059
        case 0x22c: /* cvttss2si */
3060
        case 0x32c: /* cvttsd2si */
3061
        case 0x22d: /* cvtss2si */
3062
        case 0x32d: /* cvtsd2si */
3063
            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
3064
            if (mod != 3) {
3065
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3066
                if ((b >> 8) & 1) {
3067
                    gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
3068
                } else {
3069
                    gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3070
                    gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3071
                }
3072
                op2_offset = offsetof(CPUX86State,xmm_t0);
3073
            } else {
3074
                rm = (modrm & 7) | REX_B(s);
3075
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3076
            }
3077
            sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 +
3078
                          (b & 1) * 4](op2_offset);
3079
            gen_op_mov_reg_T0[ot][reg]();
3080
            break;
3081
        case 0xc4: /* pinsrw */
3082
        case 0x1c4:
3083
            s->rip_offset = 1;
3084
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3085
            val = ldub_code(s->pc++);
3086
            if (b1) {
3087
                val &= 7;
3088
                gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
3089
            } else {
3090
                val &= 3;
3091
                gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
3092
            }
3093
            break;
3094
        case 0xc5: /* pextrw */
3095
        case 0x1c5:
3096
            if (mod != 3)
3097
                goto illegal_op;
3098
            val = ldub_code(s->pc++);
3099
            if (b1) {
3100
                val &= 7;
3101
                rm = (modrm & 7) | REX_B(s);
3102
                gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
3103
            } else {
3104
                val &= 3;
3105
                rm = (modrm & 7);
3106
                gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
3107
            }
3108
            reg = ((modrm >> 3) & 7) | rex_r;
3109
            gen_op_mov_reg_T0[OT_LONG][reg]();
3110
            break;
3111
        case 0x1d6: /* movq ea, xmm */
3112
            if (mod != 3) {
3113
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3114
                gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3115
            } else {
3116
                rm = (modrm & 7) | REX_B(s);
3117
                gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3118
                            offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3119
                gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3120
            }
3121
            break;
3122
        case 0x2d6: /* movq2dq */
3123
            gen_op_enter_mmx();
3124
            rm = (modrm & 7);
3125
            gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3126
                        offsetof(CPUX86State,fpregs[rm].mmx));
3127
            gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3128
            break;
3129
        case 0x3d6: /* movdq2q */
3130
            gen_op_enter_mmx();
3131
            rm = (modrm & 7) | REX_B(s);
3132
            gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3133
                        offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3134
            break;
3135
        case 0xd7: /* pmovmskb */
3136
        case 0x1d7:
3137
            if (mod != 3)
3138
                goto illegal_op;
3139
            if (b1) {
3140
                rm = (modrm & 7) | REX_B(s);
3141
                gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
3142
            } else {
3143
                rm = (modrm & 7);
3144
                gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
3145
            }
3146
            reg = ((modrm >> 3) & 7) | rex_r;
3147
            gen_op_mov_reg_T0[OT_LONG][reg]();
3148
            break;
3149
        default:
3150
            goto illegal_op;
3151
        }
3152
    } else {
3153
        /* generic MMX or SSE operation */
3154
        switch(b) {
3155
        case 0xf7:
3156
            /* maskmov : we must prepare A0 */
3157
            if (mod != 3)
3158
                goto illegal_op;
3159
#ifdef TARGET_X86_64
3160
            if (s->aflag == 2) {
3161
                gen_op_movq_A0_reg[R_EDI]();
3162
            } else
3163
#endif
3164
            {
3165
                gen_op_movl_A0_reg[R_EDI]();
3166
                if (s->aflag == 0)
3167
                    gen_op_andl_A0_ffff();
3168
            }
3169
            gen_add_A0_ds_seg(s);
3170
            break;
3171
        case 0x70: /* pshufx insn */
3172
        case 0xc6: /* pshufx insn */
3173
        case 0xc2: /* compare insns */
3174
            s->rip_offset = 1;
3175
            break;
3176
        default:
3177
            break;
3178
        }
3179
        if (is_xmm) {
3180
            op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3181
            if (mod != 3) {
3182
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3183
                op2_offset = offsetof(CPUX86State,xmm_t0);
3184
                if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
3185
                                b == 0xc2)) {
3186
                    /* specific case for SSE single instructions */
3187
                    if (b1 == 2) {
3188
                        /* 32 bit access */
3189
                        gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3190
                        gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
3191
                    } else {
3192
                        /* 64 bit access */
3193
                        gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
3194
                    }
3195
                } else {
3196
                    gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
3197
                }
3198
            } else {
3199
                rm = (modrm & 7) | REX_B(s);
3200
                op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3201
            }
3202
        } else {
3203
            op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3204
            if (mod != 3) {
3205
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3206
                op2_offset = offsetof(CPUX86State,mmx_t0);
3207
                gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
3208
            } else {
3209
                rm = (modrm & 7);
3210
                op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3211
            }
3212
        }
3213
        switch(b) {
3214
        case 0x70: /* pshufx insn */
3215
        case 0xc6: /* pshufx insn */
3216
            val = ldub_code(s->pc++);
3217
            sse_op3 = (GenOpFunc3 *)sse_op2;
3218
            sse_op3(op1_offset, op2_offset, val);
3219
            break;
3220
        case 0xc2:
3221
            /* compare insns */
3222
            val = ldub_code(s->pc++);
3223
            if (val >= 8)
3224
                goto illegal_op;
3225
            sse_op2 = sse_op_table4[val][b1];
3226
            sse_op2(op1_offset, op2_offset);
3227
            break;
3228
        default:
3229
            sse_op2(op1_offset, op2_offset);
3230
            break;
3231
        }
3232
        if (b == 0x2e || b == 0x2f) {
3233
            s->cc_op = CC_OP_EFLAGS;
3234
        }
3235
    }
3236
}
3237

    
3238

    
3239
/* convert one instruction. s->is_jmp is set if the translation must
3240
   be stopped. Return the next pc value */
3241
static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3242
{
3243
    int b, prefixes, aflag, dflag;
3244
    int shift, ot;
3245
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3246
    target_ulong next_eip, tval;
3247
    int rex_w, rex_r;
3248

    
3249
    s->pc = pc_start;
3250
    prefixes = 0;
3251
    aflag = s->code32;
3252
    dflag = s->code32;
3253
    s->override = -1;
3254
    rex_w = -1;
3255
    rex_r = 0;
3256
#ifdef TARGET_X86_64
3257
    s->rex_x = 0;
3258
    s->rex_b = 0;
3259
    x86_64_hregs = 0;
3260
#endif
3261
    s->rip_offset = 0; /* for relative ip address */
3262
 next_byte:
3263
    b = ldub_code(s->pc);
3264
    s->pc++;
3265
    /* check prefixes */
3266
#ifdef TARGET_X86_64
3267
    if (CODE64(s)) {
3268
        switch (b) {
3269
        case 0xf3:
3270
            prefixes |= PREFIX_REPZ;
3271
            goto next_byte;
3272
        case 0xf2:
3273
            prefixes |= PREFIX_REPNZ;
3274
            goto next_byte;
3275
        case 0xf0:
3276
            prefixes |= PREFIX_LOCK;
3277
            goto next_byte;
3278
        case 0x2e:
3279
            s->override = R_CS;
3280
            goto next_byte;
3281
        case 0x36:
3282
            s->override = R_SS;
3283
            goto next_byte;
3284
        case 0x3e:
3285
            s->override = R_DS;
3286
            goto next_byte;
3287
        case 0x26:
3288
            s->override = R_ES;
3289
            goto next_byte;
3290
        case 0x64:
3291
            s->override = R_FS;
3292
            goto next_byte;
3293
        case 0x65:
3294
            s->override = R_GS;
3295
            goto next_byte;
3296
        case 0x66:
3297
            prefixes |= PREFIX_DATA;
3298
            goto next_byte;
3299
        case 0x67:
3300
            prefixes |= PREFIX_ADR;
3301
            goto next_byte;
3302
        case 0x40 ... 0x4f:
3303
            /* REX prefix */
3304
            rex_w = (b >> 3) & 1;
3305
            rex_r = (b & 0x4) << 1;
3306
            s->rex_x = (b & 0x2) << 2;
3307
            REX_B(s) = (b & 0x1) << 3;
3308
            x86_64_hregs = 1; /* select uniform byte register addressing */
3309
            goto next_byte;
3310
        }
3311
        if (rex_w == 1) {
3312
            /* 0x66 is ignored if rex.w is set */
3313
            dflag = 2;
3314
        } else {
3315
            if (prefixes & PREFIX_DATA)
3316
                dflag ^= 1;
3317
        }
3318
        if (!(prefixes & PREFIX_ADR))
3319
            aflag = 2;
3320
    } else
3321
#endif
3322
    {
3323
        switch (b) {
3324
        case 0xf3:
3325
            prefixes |= PREFIX_REPZ;
3326
            goto next_byte;
3327
        case 0xf2:
3328
            prefixes |= PREFIX_REPNZ;
3329
            goto next_byte;
3330
        case 0xf0:
3331
            prefixes |= PREFIX_LOCK;
3332
            goto next_byte;
3333
        case 0x2e:
3334
            s->override = R_CS;
3335
            goto next_byte;
3336
        case 0x36:
3337
            s->override = R_SS;
3338
            goto next_byte;
3339
        case 0x3e:
3340
            s->override = R_DS;
3341
            goto next_byte;
3342
        case 0x26:
3343
            s->override = R_ES;
3344
            goto next_byte;
3345
        case 0x64:
3346
            s->override = R_FS;
3347
            goto next_byte;
3348
        case 0x65:
3349
            s->override = R_GS;
3350
            goto next_byte;
3351
        case 0x66:
3352
            prefixes |= PREFIX_DATA;
3353
            goto next_byte;
3354
        case 0x67:
3355
            prefixes |= PREFIX_ADR;
3356
            goto next_byte;
3357
        }
3358
        if (prefixes & PREFIX_DATA)
3359
            dflag ^= 1;
3360
        if (prefixes & PREFIX_ADR)
3361
            aflag ^= 1;
3362
    }
3363

    
3364
    s->prefix = prefixes;
3365
    s->aflag = aflag;
3366
    s->dflag = dflag;
3367

    
3368
    /* lock generation */
3369
    if (prefixes & PREFIX_LOCK)
3370
        gen_op_lock();
3371

    
3372
    /* now check op code */
3373
 reswitch:
3374
    switch(b) {
3375
    case 0x0f:
3376
        /**************************/
3377
        /* extended op code */
3378
        b = ldub_code(s->pc++) | 0x100;
3379
        goto reswitch;
3380

    
3381
        /**************************/
3382
        /* arith & logic */
3383
    case 0x00 ... 0x05:
3384
    case 0x08 ... 0x0d:
3385
    case 0x10 ... 0x15:
3386
    case 0x18 ... 0x1d:
3387
    case 0x20 ... 0x25:
3388
    case 0x28 ... 0x2d:
3389
    case 0x30 ... 0x35:
3390
    case 0x38 ... 0x3d:
3391
        {
3392
            int op, f, val;
3393
            op = (b >> 3) & 7;
3394
            f = (b >> 1) & 3;
3395

    
3396
            if ((b & 1) == 0)
3397
                ot = OT_BYTE;
3398
            else
3399
                ot = dflag + OT_WORD;
3400

    
3401
            switch(f) {
3402
            case 0: /* OP Ev, Gv */
3403
                modrm = ldub_code(s->pc++);
3404
                reg = ((modrm >> 3) & 7) | rex_r;
3405
                mod = (modrm >> 6) & 3;
3406
                rm = (modrm & 7) | REX_B(s);
3407
                if (mod != 3) {
3408
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3409
                    opreg = OR_TMP0;
3410
                } else if (op == OP_XORL && rm == reg) {
3411
                xor_zero:
3412
                    /* xor reg, reg optimisation */
3413
                    gen_op_movl_T0_0();
3414
                    s->cc_op = CC_OP_LOGICB + ot;
3415
                    gen_op_mov_reg_T0[ot][reg]();
3416
                    gen_op_update1_cc();
3417
                    break;
3418
                } else {
3419
                    opreg = rm;
3420
                }
3421
                gen_op_mov_TN_reg[ot][1][reg]();
3422
                gen_op(s, op, ot, opreg);
3423
                break;
3424
            case 1: /* OP Gv, Ev */
3425
                modrm = ldub_code(s->pc++);
3426
                mod = (modrm >> 6) & 3;
3427
                reg = ((modrm >> 3) & 7) | rex_r;
3428
                rm = (modrm & 7) | REX_B(s);
3429
                if (mod != 3) {
3430
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3431
                    gen_op_ld_T1_A0[ot + s->mem_index]();
3432
                } else if (op == OP_XORL && rm == reg) {
3433
                    goto xor_zero;
3434
                } else {
3435
                    gen_op_mov_TN_reg[ot][1][rm]();
3436
                }
3437
                gen_op(s, op, ot, reg);
3438
                break;
3439
            case 2: /* OP A, Iv */
3440
                val = insn_get(s, ot);
3441
                gen_op_movl_T1_im(val);
3442
                gen_op(s, op, ot, OR_EAX);
3443
                break;
3444
            }
3445
        }
3446
        break;
3447

    
3448
    case 0x80: /* GRP1 */
3449
    case 0x81:
3450
    case 0x82:
3451
    case 0x83:
3452
        {
3453
            int val;
3454

    
3455
            if ((b & 1) == 0)
3456
                ot = OT_BYTE;
3457
            else
3458
                ot = dflag + OT_WORD;
3459

    
3460
            modrm = ldub_code(s->pc++);
3461
            mod = (modrm >> 6) & 3;
3462
            rm = (modrm & 7) | REX_B(s);
3463
            op = (modrm >> 3) & 7;
3464

    
3465
            if (mod != 3) {
3466
                if (b == 0x83)
3467
                    s->rip_offset = 1;
3468
                else
3469
                    s->rip_offset = insn_const_size(ot);
3470
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3471
                opreg = OR_TMP0;
3472
            } else {
3473
                opreg = rm;
3474
            }
3475

    
3476
            switch(b) {
3477
            default:
3478
            case 0x80:
3479
            case 0x81:
3480
            case 0x82:
3481
                val = insn_get(s, ot);
3482
                break;
3483
            case 0x83:
3484
                val = (int8_t)insn_get(s, OT_BYTE);
3485
                break;
3486
            }
3487
            gen_op_movl_T1_im(val);
3488
            gen_op(s, op, ot, opreg);
3489
        }
3490
        break;
3491

    
3492
        /**************************/
3493
        /* inc, dec, and other misc arith */
3494
    case 0x40 ... 0x47: /* inc Gv */
3495
        ot = dflag ? OT_LONG : OT_WORD;
3496
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
3497
        break;
3498
    case 0x48 ... 0x4f: /* dec Gv */
3499
        ot = dflag ? OT_LONG : OT_WORD;
3500
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
3501
        break;
3502
    case 0xf6: /* GRP3 */
3503
    case 0xf7:
3504
        if ((b & 1) == 0)
3505
            ot = OT_BYTE;
3506
        else
3507
            ot = dflag + OT_WORD;
3508

    
3509
        modrm = ldub_code(s->pc++);
3510
        mod = (modrm >> 6) & 3;
3511
        rm = (modrm & 7) | REX_B(s);
3512
        op = (modrm >> 3) & 7;
3513
        if (mod != 3) {
3514
            if (op == 0)
3515
                s->rip_offset = insn_const_size(ot);
3516
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3517
            gen_op_ld_T0_A0[ot + s->mem_index]();
3518
        } else {
3519
            gen_op_mov_TN_reg[ot][0][rm]();
3520
        }
3521

    
3522
        switch(op) {
3523
        case 0: /* test */
3524
            val = insn_get(s, ot);
3525
            gen_op_movl_T1_im(val);
3526
            gen_op_testl_T0_T1_cc();
3527
            s->cc_op = CC_OP_LOGICB + ot;
3528
            break;
3529
        case 2: /* not */
3530
            gen_op_notl_T0();
3531
            if (mod != 3) {
3532
                gen_op_st_T0_A0[ot + s->mem_index]();
3533
            } else {
3534
                gen_op_mov_reg_T0[ot][rm]();
3535
            }
3536
            break;
3537
        case 3: /* neg */
3538
            gen_op_negl_T0();
3539
            if (mod != 3) {
3540
                gen_op_st_T0_A0[ot + s->mem_index]();
3541
            } else {
3542
                gen_op_mov_reg_T0[ot][rm]();
3543
            }
3544
            gen_op_update_neg_cc();
3545
            s->cc_op = CC_OP_SUBB + ot;
3546
            break;
3547
        case 4: /* mul */
3548
            switch(ot) {
3549
            case OT_BYTE:
3550
                gen_op_mulb_AL_T0();
3551
                s->cc_op = CC_OP_MULB;
3552
                break;
3553
            case OT_WORD:
3554
                gen_op_mulw_AX_T0();
3555
                s->cc_op = CC_OP_MULW;
3556
                break;
3557
            default:
3558
            case OT_LONG:
3559
                gen_op_mull_EAX_T0();
3560
                s->cc_op = CC_OP_MULL;
3561
                break;
3562
#ifdef TARGET_X86_64
3563
            case OT_QUAD:
3564
                gen_op_mulq_EAX_T0();
3565
                s->cc_op = CC_OP_MULQ;
3566
                break;
3567
#endif
3568
            }
3569
            break;
3570
        case 5: /* imul */
3571
            switch(ot) {
3572
            case OT_BYTE:
3573
                gen_op_imulb_AL_T0();
3574
                s->cc_op = CC_OP_MULB;
3575
                break;
3576
            case OT_WORD:
3577
                gen_op_imulw_AX_T0();
3578
                s->cc_op = CC_OP_MULW;
3579
                break;
3580
            default:
3581
            case OT_LONG:
3582
                gen_op_imull_EAX_T0();
3583
                s->cc_op = CC_OP_MULL;
3584
                break;
3585
#ifdef TARGET_X86_64
3586
            case OT_QUAD:
3587
                gen_op_imulq_EAX_T0();
3588
                s->cc_op = CC_OP_MULQ;
3589
                break;
3590
#endif
3591
            }
3592
            break;
3593
        case 6: /* div */
3594
            switch(ot) {
3595
            case OT_BYTE:
3596
                gen_jmp_im(pc_start - s->cs_base);
3597
                gen_op_divb_AL_T0();
3598
                break;
3599
            case OT_WORD:
3600
                gen_jmp_im(pc_start - s->cs_base);
3601
                gen_op_divw_AX_T0();
3602
                break;
3603
            default:
3604
            case OT_LONG:
3605
                gen_jmp_im(pc_start - s->cs_base);
3606
                gen_op_divl_EAX_T0();
3607
                break;
3608
#ifdef TARGET_X86_64
3609
            case OT_QUAD:
3610
                gen_jmp_im(pc_start - s->cs_base);
3611
                gen_op_divq_EAX_T0();
3612
                break;
3613
#endif
3614
            }
3615
            break;
3616
        case 7: /* idiv */
3617
            switch(ot) {
3618
            case OT_BYTE:
3619
                gen_jmp_im(pc_start - s->cs_base);
3620
                gen_op_idivb_AL_T0();
3621
                break;
3622
            case OT_WORD:
3623
                gen_jmp_im(pc_start - s->cs_base);
3624
                gen_op_idivw_AX_T0();
3625
                break;
3626
            default:
3627
            case OT_LONG:
3628
                gen_jmp_im(pc_start - s->cs_base);
3629
                gen_op_idivl_EAX_T0();
3630
                break;
3631
#ifdef TARGET_X86_64
3632
            case OT_QUAD:
3633
                gen_jmp_im(pc_start - s->cs_base);
3634
                gen_op_idivq_EAX_T0();
3635
                break;
3636
#endif
3637
            }
3638
            break;
3639
        default:
3640
            goto illegal_op;
3641
        }
3642
        break;
3643

    
3644
    case 0xfe: /* GRP4 */
3645
    case 0xff: /* GRP5 */
3646
        if ((b & 1) == 0)
3647
            ot = OT_BYTE;
3648
        else
3649
            ot = dflag + OT_WORD;
3650

    
3651
        modrm = ldub_code(s->pc++);
3652
        mod = (modrm >> 6) & 3;
3653
        rm = (modrm & 7) | REX_B(s);
3654
        op = (modrm >> 3) & 7;
3655
        if (op >= 2 && b == 0xfe) {
3656
            goto illegal_op;
3657
        }
3658
        if (CODE64(s)) {
3659
            if (op == 2 || op == 4) {
3660
                /* operand size for jumps is 64 bit */
3661
                ot = OT_QUAD;
3662
            } else if (op == 3 || op == 5) {
3663
                /* for call calls, the operand is 16 or 32 bit, even
3664
                   in long mode */
3665
                ot = dflag ? OT_LONG : OT_WORD;
3666
            } else if (op == 6) {
3667
                /* default push size is 64 bit */
3668
                ot = dflag ? OT_QUAD : OT_WORD;
3669
            }
3670
        }
3671
        if (mod != 3) {
3672
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3673
            if (op >= 2 && op != 3 && op != 5)
3674
                gen_op_ld_T0_A0[ot + s->mem_index]();
3675
        } else {
3676
            gen_op_mov_TN_reg[ot][0][rm]();
3677
        }
3678

    
3679
        switch(op) {
3680
        case 0: /* inc Ev */
3681
            if (mod != 3)
3682
                opreg = OR_TMP0;
3683
            else
3684
                opreg = rm;
3685
            gen_inc(s, ot, opreg, 1);
3686
            break;
3687
        case 1: /* dec Ev */
3688
            if (mod != 3)
3689
                opreg = OR_TMP0;
3690
            else
3691
                opreg = rm;
3692
            gen_inc(s, ot, opreg, -1);
3693
            break;
3694
        case 2: /* call Ev */
3695
            /* XXX: optimize if memory (no 'and' is necessary) */
3696
            if (s->dflag == 0)
3697
                gen_op_andl_T0_ffff();
3698
            next_eip = s->pc - s->cs_base;
3699
            gen_movtl_T1_im(next_eip);
3700
            gen_push_T1(s);
3701
            gen_op_jmp_T0();
3702
            gen_eob(s);
3703
            break;
3704
        case 3: /* lcall Ev */
3705
            gen_op_ld_T1_A0[ot + s->mem_index]();
3706
            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3707
            gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3708
        do_lcall:
3709
            if (s->pe && !s->vm86) {
3710
                if (s->cc_op != CC_OP_DYNAMIC)
3711
                    gen_op_set_cc_op(s->cc_op);
3712
                gen_jmp_im(pc_start - s->cs_base);
3713
                gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
3714
            } else {
3715
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3716
            }
3717
            gen_eob(s);
3718
            break;
3719
        case 4: /* jmp Ev */
3720
            if (s->dflag == 0)
3721
                gen_op_andl_T0_ffff();
3722
            gen_op_jmp_T0();
3723
            gen_eob(s);
3724
            break;
3725
        case 5: /* ljmp Ev */
3726
            gen_op_ld_T1_A0[ot + s->mem_index]();
3727
            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3728
            gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3729
        do_ljmp:
3730
            if (s->pe && !s->vm86) {
3731
                if (s->cc_op != CC_OP_DYNAMIC)
3732
                    gen_op_set_cc_op(s->cc_op);
3733
                gen_jmp_im(pc_start - s->cs_base);
3734
                gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
3735
            } else {
3736
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3737
                gen_op_movl_T0_T1();
3738
                gen_op_jmp_T0();
3739
            }
3740
            gen_eob(s);
3741
            break;
3742
        case 6: /* push Ev */
3743
            gen_push_T0(s);
3744
            break;
3745
        default:
3746
            goto illegal_op;
3747
        }
3748
        break;
3749

    
3750
    case 0x84: /* test Ev, Gv */
3751
    case 0x85:
3752
        if ((b & 1) == 0)
3753
            ot = OT_BYTE;
3754
        else
3755
            ot = dflag + OT_WORD;
3756

    
3757
        modrm = ldub_code(s->pc++);
3758
        mod = (modrm >> 6) & 3;
3759
        rm = (modrm & 7) | REX_B(s);
3760
        reg = ((modrm >> 3) & 7) | rex_r;
3761

    
3762
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3763
        gen_op_mov_TN_reg[ot][1][reg]();
3764
        gen_op_testl_T0_T1_cc();
3765
        s->cc_op = CC_OP_LOGICB + ot;
3766
        break;
3767

    
3768
    case 0xa8: /* test eAX, Iv */
3769
    case 0xa9:
3770
        if ((b & 1) == 0)
3771
            ot = OT_BYTE;
3772
        else
3773
            ot = dflag + OT_WORD;
3774
        val = insn_get(s, ot);
3775

    
3776
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
3777
        gen_op_movl_T1_im(val);
3778
        gen_op_testl_T0_T1_cc();
3779
        s->cc_op = CC_OP_LOGICB + ot;
3780
        break;
3781

    
3782
    case 0x98: /* CWDE/CBW */
3783
#ifdef TARGET_X86_64
3784
        if (dflag == 2) {
3785
            gen_op_movslq_RAX_EAX();
3786
        } else
3787
#endif
3788
        if (dflag == 1)
3789
            gen_op_movswl_EAX_AX();
3790
        else
3791
            gen_op_movsbw_AX_AL();
3792
        break;
3793
    case 0x99: /* CDQ/CWD */
3794
#ifdef TARGET_X86_64
3795
        if (dflag == 2) {
3796
            gen_op_movsqo_RDX_RAX();
3797
        } else
3798
#endif
3799
        if (dflag == 1)
3800
            gen_op_movslq_EDX_EAX();
3801
        else
3802
            gen_op_movswl_DX_AX();
3803
        break;
3804
    case 0x1af: /* imul Gv, Ev */
3805
    case 0x69: /* imul Gv, Ev, I */
3806
    case 0x6b:
3807
        ot = dflag + OT_WORD;
3808
        modrm = ldub_code(s->pc++);
3809
        reg = ((modrm >> 3) & 7) | rex_r;
3810
        if (b == 0x69)
3811
            s->rip_offset = insn_const_size(ot);
3812
        else if (b == 0x6b)
3813
            s->rip_offset = 1;
3814
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3815
        if (b == 0x69) {
3816
            val = insn_get(s, ot);
3817
            gen_op_movl_T1_im(val);
3818
        } else if (b == 0x6b) {
3819
            val = (int8_t)insn_get(s, OT_BYTE);
3820
            gen_op_movl_T1_im(val);
3821
        } else {
3822
            gen_op_mov_TN_reg[ot][1][reg]();
3823
        }
3824

    
3825
#ifdef TARGET_X86_64
3826
        if (ot == OT_QUAD) {
3827
            gen_op_imulq_T0_T1();
3828
        } else
3829
#endif
3830
        if (ot == OT_LONG) {
3831
            gen_op_imull_T0_T1();
3832
        } else {
3833
            gen_op_imulw_T0_T1();
3834
        }
3835
        gen_op_mov_reg_T0[ot][reg]();
3836
        s->cc_op = CC_OP_MULB + ot;
3837
        break;
3838
    case 0x1c0:
3839
    case 0x1c1: /* xadd Ev, Gv */
3840
        if ((b & 1) == 0)
3841
            ot = OT_BYTE;
3842
        else
3843
            ot = dflag + OT_WORD;
3844
        modrm = ldub_code(s->pc++);
3845
        reg = ((modrm >> 3) & 7) | rex_r;
3846
        mod = (modrm >> 6) & 3;
3847
        if (mod == 3) {
3848
            rm = (modrm & 7) | REX_B(s);
3849
            gen_op_mov_TN_reg[ot][0][reg]();
3850
            gen_op_mov_TN_reg[ot][1][rm]();
3851
            gen_op_addl_T0_T1();
3852
            gen_op_mov_reg_T1[ot][reg]();
3853
            gen_op_mov_reg_T0[ot][rm]();
3854
        } else {
3855
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3856
            gen_op_mov_TN_reg[ot][0][reg]();
3857
            gen_op_ld_T1_A0[ot + s->mem_index]();
3858
            gen_op_addl_T0_T1();
3859
            gen_op_st_T0_A0[ot + s->mem_index]();
3860
            gen_op_mov_reg_T1[ot][reg]();
3861
        }
3862
        gen_op_update2_cc();
3863
        s->cc_op = CC_OP_ADDB + ot;
3864
        break;
3865
    case 0x1b0:
3866
    case 0x1b1: /* cmpxchg Ev, Gv */
3867
        if ((b & 1) == 0)
3868
            ot = OT_BYTE;
3869
        else
3870
            ot = dflag + OT_WORD;
3871
        modrm = ldub_code(s->pc++);
3872
        reg = ((modrm >> 3) & 7) | rex_r;
3873
        mod = (modrm >> 6) & 3;
3874
        gen_op_mov_TN_reg[ot][1][reg]();
3875
        if (mod == 3) {
3876
            rm = (modrm & 7) | REX_B(s);
3877
            gen_op_mov_TN_reg[ot][0][rm]();
3878
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3879
            gen_op_mov_reg_T0[ot][rm]();
3880
        } else {
3881
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3882
            gen_op_ld_T0_A0[ot + s->mem_index]();
3883
            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
3884
        }
3885
        s->cc_op = CC_OP_SUBB + ot;
3886
        break;
3887
    case 0x1c7: /* cmpxchg8b */
3888
        modrm = ldub_code(s->pc++);
3889
        mod = (modrm >> 6) & 3;
3890
        if (mod == 3)
3891
            goto illegal_op;
3892
        gen_jmp_im(pc_start - s->cs_base);
3893
        if (s->cc_op != CC_OP_DYNAMIC)
3894
            gen_op_set_cc_op(s->cc_op);
3895
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3896
        gen_op_cmpxchg8b();
3897
        s->cc_op = CC_OP_EFLAGS;
3898
        break;
3899

    
3900
        /**************************/
3901
        /* push/pop */
3902
    case 0x50 ... 0x57: /* push */
3903
        gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
3904
        gen_push_T0(s);
3905
        break;
3906
    case 0x58 ... 0x5f: /* pop */
3907
        if (CODE64(s)) {
3908
            ot = dflag ? OT_QUAD : OT_WORD;
3909
        } else {
3910
            ot = dflag + OT_WORD;
3911
        }
3912
        gen_pop_T0(s);
3913
        /* NOTE: order is important for pop %sp */
3914
        gen_pop_update(s);
3915
        gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
3916
        break;
3917
    case 0x60: /* pusha */
3918
        if (CODE64(s))
3919
            goto illegal_op;
3920
        gen_pusha(s);
3921
        break;
3922
    case 0x61: /* popa */
3923
        if (CODE64(s))
3924
            goto illegal_op;
3925
        gen_popa(s);
3926
        break;
3927
    case 0x68: /* push Iv */
3928
    case 0x6a:
3929
        if (CODE64(s)) {
3930
            ot = dflag ? OT_QUAD : OT_WORD;
3931
        } else {
3932
            ot = dflag + OT_WORD;
3933
        }
3934
        if (b == 0x68)
3935
            val = insn_get(s, ot);
3936
        else
3937
            val = (int8_t)insn_get(s, OT_BYTE);
3938
        gen_op_movl_T0_im(val);
3939
        gen_push_T0(s);
3940
        break;
3941
    case 0x8f: /* pop Ev */
3942
        if (CODE64(s)) {
3943
            ot = dflag ? OT_QUAD : OT_WORD;
3944
        } else {
3945
            ot = dflag + OT_WORD;
3946
        }
3947
        modrm = ldub_code(s->pc++);
3948
        mod = (modrm >> 6) & 3;
3949
        gen_pop_T0(s);
3950
        if (mod == 3) {
3951
            /* NOTE: order is important for pop %sp */
3952
            gen_pop_update(s);
3953
            rm = (modrm & 7) | REX_B(s);
3954
            gen_op_mov_reg_T0[ot][rm]();
3955
        } else {
3956
            /* NOTE: order is important too for MMU exceptions */
3957
            s->popl_esp_hack = 1 << ot;
3958
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3959
            s->popl_esp_hack = 0;
3960
            gen_pop_update(s);
3961
        }
3962
        break;
3963
    case 0xc8: /* enter */
3964
        {
3965
            int level;
3966
            val = lduw_code(s->pc);
3967
            s->pc += 2;
3968
            level = ldub_code(s->pc++);
3969
            gen_enter(s, val, level);
3970
        }
3971
        break;
3972
    case 0xc9: /* leave */
3973
        /* XXX: exception not precise (ESP is updated before potential exception) */
3974
        if (CODE64(s)) {
3975
            gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3976
            gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3977
        } else if (s->ss32) {
3978
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3979
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3980
        } else {
3981
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3982
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3983
        }
3984
        gen_pop_T0(s);
3985
        if (CODE64(s)) {
3986
            ot = dflag ? OT_QUAD : OT_WORD;
3987
        } else {
3988
            ot = dflag + OT_WORD;
3989
        }
3990
        gen_op_mov_reg_T0[ot][R_EBP]();
3991
        gen_pop_update(s);
3992
        break;
3993
    case 0x06: /* push es */
3994
    case 0x0e: /* push cs */
3995
    case 0x16: /* push ss */
3996
    case 0x1e: /* push ds */
3997
        if (CODE64(s))
3998
            goto illegal_op;
3999
        gen_op_movl_T0_seg(b >> 3);
4000
        gen_push_T0(s);
4001
        break;
4002
    case 0x1a0: /* push fs */
4003
    case 0x1a8: /* push gs */
4004
        gen_op_movl_T0_seg((b >> 3) & 7);
4005
        gen_push_T0(s);
4006
        break;
4007
    case 0x07: /* pop es */
4008
    case 0x17: /* pop ss */
4009
    case 0x1f: /* pop ds */
4010
        if (CODE64(s))
4011
            goto illegal_op;
4012
        reg = b >> 3;
4013
        gen_pop_T0(s);
4014
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4015
        gen_pop_update(s);
4016
        if (reg == R_SS) {
4017
            /* if reg == SS, inhibit interrupts/trace. */
4018
            /* If several instructions disable interrupts, only the
4019
               _first_ does it */
4020
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4021
                gen_op_set_inhibit_irq();
4022
            s->tf = 0;
4023
        }
4024
        if (s->is_jmp) {
4025
            gen_jmp_im(s->pc - s->cs_base);
4026
            gen_eob(s);
4027
        }
4028
        break;
4029
    case 0x1a1: /* pop fs */
4030
    case 0x1a9: /* pop gs */
4031
        gen_pop_T0(s);
4032
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
4033
        gen_pop_update(s);
4034
        if (s->is_jmp) {
4035
            gen_jmp_im(s->pc - s->cs_base);
4036
            gen_eob(s);
4037
        }
4038
        break;
4039

    
4040
        /**************************/
4041
        /* mov */
4042
    case 0x88:
4043
    case 0x89: /* mov Gv, Ev */
4044
        if ((b & 1) == 0)
4045
            ot = OT_BYTE;
4046
        else
4047
            ot = dflag + OT_WORD;
4048
        modrm = ldub_code(s->pc++);
4049
        reg = ((modrm >> 3) & 7) | rex_r;
4050

    
4051
        /* generate a generic store */
4052
        gen_ldst_modrm(s, modrm, ot, reg, 1);
4053
        break;
4054
    case 0xc6:
4055
    case 0xc7: /* mov Ev, Iv */
4056
        if ((b & 1) == 0)
4057
            ot = OT_BYTE;
4058
        else
4059
            ot = dflag + OT_WORD;
4060
        modrm = ldub_code(s->pc++);
4061
        mod = (modrm >> 6) & 3;
4062
        if (mod != 3) {
4063
            s->rip_offset = insn_const_size(ot);
4064
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4065
        }
4066
        val = insn_get(s, ot);
4067
        gen_op_movl_T0_im(val);
4068
        if (mod != 3)
4069
            gen_op_st_T0_A0[ot + s->mem_index]();
4070
        else
4071
            gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
4072
        break;
4073
    case 0x8a:
4074
    case 0x8b: /* mov Ev, Gv */
4075
        if ((b & 1) == 0)
4076
            ot = OT_BYTE;
4077
        else
4078
            ot = OT_WORD + dflag;
4079
        modrm = ldub_code(s->pc++);
4080
        reg = ((modrm >> 3) & 7) | rex_r;
4081

    
4082
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4083
        gen_op_mov_reg_T0[ot][reg]();
4084
        break;
4085
    case 0x8e: /* mov seg, Gv */
4086
        modrm = ldub_code(s->pc++);
4087
        reg = (modrm >> 3) & 7;
4088
        if (reg >= 6 || reg == R_CS)
4089
            goto illegal_op;
4090
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4091
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
4092
        if (reg == R_SS) {
4093
            /* if reg == SS, inhibit interrupts/trace */
4094
            /* If several instructions disable interrupts, only the
4095
               _first_ does it */
4096
            if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
4097
                gen_op_set_inhibit_irq();
4098
            s->tf = 0;
4099
        }
4100
        if (s->is_jmp) {
4101
            gen_jmp_im(s->pc - s->cs_base);
4102
            gen_eob(s);
4103
        }
4104
        break;
4105
    case 0x8c: /* mov Gv, seg */
4106
        modrm = ldub_code(s->pc++);
4107
        reg = (modrm >> 3) & 7;
4108
        mod = (modrm >> 6) & 3;
4109
        if (reg >= 6)
4110
            goto illegal_op;
4111
        gen_op_movl_T0_seg(reg);
4112
        if (mod == 3)
4113
            ot = OT_WORD + dflag;
4114
        else
4115
            ot = OT_WORD;
4116
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
4117
        break;
4118

    
4119
    case 0x1b6: /* movzbS Gv, Eb */
4120
    case 0x1b7: /* movzwS Gv, Eb */
4121
    case 0x1be: /* movsbS Gv, Eb */
4122
    case 0x1bf: /* movswS Gv, Eb */
4123
        {
4124
            int d_ot;
4125
            /* d_ot is the size of destination */
4126
            d_ot = dflag + OT_WORD;
4127
            /* ot is the size of source */
4128
            ot = (b & 1) + OT_BYTE;
4129
            modrm = ldub_code(s->pc++);
4130
            reg = ((modrm >> 3) & 7) | rex_r;
4131
            mod = (modrm >> 6) & 3;
4132
            rm = (modrm & 7) | REX_B(s);
4133

    
4134
            if (mod == 3) {
4135
                gen_op_mov_TN_reg[ot][0][rm]();
4136
                switch(ot | (b & 8)) {
4137
                case OT_BYTE:
4138
                    gen_op_movzbl_T0_T0();
4139
                    break;
4140
                case OT_BYTE | 8:
4141
                    gen_op_movsbl_T0_T0();
4142
                    break;
4143
                case OT_WORD:
4144
                    gen_op_movzwl_T0_T0();
4145
                    break;
4146
                default:
4147
                case OT_WORD | 8:
4148
                    gen_op_movswl_T0_T0();
4149
                    break;
4150
                }
4151
                gen_op_mov_reg_T0[d_ot][reg]();
4152
            } else {
4153
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4154
                if (b & 8) {
4155
                    gen_op_lds_T0_A0[ot + s->mem_index]();
4156
                } else {
4157
                    gen_op_ldu_T0_A0[ot + s->mem_index]();
4158
                }
4159
                gen_op_mov_reg_T0[d_ot][reg]();
4160
            }
4161
        }
4162
        break;
4163

    
4164
    case 0x8d: /* lea */
4165
        ot = dflag + OT_WORD;
4166
        modrm = ldub_code(s->pc++);
4167
        mod = (modrm >> 6) & 3;
4168
        if (mod == 3)
4169
            goto illegal_op;
4170
        reg = ((modrm >> 3) & 7) | rex_r;
4171
        /* we must ensure that no segment is added */
4172
        s->override = -1;
4173
        val = s->addseg;
4174
        s->addseg = 0;
4175
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4176
        s->addseg = val;
4177
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
4178
        break;
4179

    
4180
    case 0xa0: /* mov EAX, Ov */
4181
    case 0xa1:
4182
    case 0xa2: /* mov Ov, EAX */
4183
    case 0xa3:
4184
        {
4185
            target_ulong offset_addr;
4186

    
4187
            if ((b & 1) == 0)
4188
                ot = OT_BYTE;
4189
            else
4190
                ot = dflag + OT_WORD;
4191
#ifdef TARGET_X86_64
4192
            if (s->aflag == 2) {
4193
                offset_addr = ldq_code(s->pc);
4194
                s->pc += 8;
4195
                if (offset_addr == (int32_t)offset_addr)
4196
                    gen_op_movq_A0_im(offset_addr);
4197
                else
4198
                    gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
4199
            } else
4200
#endif
4201
            {
4202
                if (s->aflag) {
4203
                    offset_addr = insn_get(s, OT_LONG);
4204
                } else {
4205
                    offset_addr = insn_get(s, OT_WORD);
4206
                }
4207
                gen_op_movl_A0_im(offset_addr);
4208
            }
4209
            gen_add_A0_ds_seg(s);
4210
            if ((b & 2) == 0) {
4211
                gen_op_ld_T0_A0[ot + s->mem_index]();
4212
                gen_op_mov_reg_T0[ot][R_EAX]();
4213
            } else {
4214
                gen_op_mov_TN_reg[ot][0][R_EAX]();
4215
                gen_op_st_T0_A0[ot + s->mem_index]();
4216
            }
4217
        }
4218
        break;
4219
    case 0xd7: /* xlat */
4220
#ifdef TARGET_X86_64
4221
        if (s->aflag == 2) {
4222
            gen_op_movq_A0_reg[R_EBX]();
4223
            gen_op_addq_A0_AL();
4224
        } else
4225
#endif
4226
        {
4227
            gen_op_movl_A0_reg[R_EBX]();
4228
            gen_op_addl_A0_AL();
4229
            if (s->aflag == 0)
4230
                gen_op_andl_A0_ffff();
4231
        }
4232
        gen_add_A0_ds_seg(s);
4233
        gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4234
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4235
        break;
4236
    case 0xb0 ... 0xb7: /* mov R, Ib */
4237
        val = insn_get(s, OT_BYTE);
4238
        gen_op_movl_T0_im(val);
4239
        gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
4240
        break;
4241
    case 0xb8 ... 0xbf: /* mov R, Iv */
4242
#ifdef TARGET_X86_64
4243
        if (dflag == 2) {
4244
            uint64_t tmp;
4245
            /* 64 bit case */
4246
            tmp = ldq_code(s->pc);
4247
            s->pc += 8;
4248
            reg = (b & 7) | REX_B(s);
4249
            gen_movtl_T0_im(tmp);
4250
            gen_op_mov_reg_T0[OT_QUAD][reg]();
4251
        } else
4252
#endif
4253
        {
4254
            ot = dflag ? OT_LONG : OT_WORD;
4255
            val = insn_get(s, ot);
4256
            reg = (b & 7) | REX_B(s);
4257
            gen_op_movl_T0_im(val);
4258
            gen_op_mov_reg_T0[ot][reg]();
4259
        }
4260
        break;
4261

    
4262
    case 0x91 ... 0x97: /* xchg R, EAX */
4263
        ot = dflag + OT_WORD;
4264
        reg = (b & 7) | REX_B(s);
4265
        rm = R_EAX;
4266
        goto do_xchg_reg;
4267
    case 0x86:
4268
    case 0x87: /* xchg Ev, Gv */
4269
        if ((b & 1) == 0)
4270
            ot = OT_BYTE;
4271
        else
4272
            ot = dflag + OT_WORD;
4273
        modrm = ldub_code(s->pc++);
4274
        reg = ((modrm >> 3) & 7) | rex_r;
4275
        mod = (modrm >> 6) & 3;
4276
        if (mod == 3) {
4277
            rm = (modrm & 7) | REX_B(s);
4278
        do_xchg_reg:
4279
            gen_op_mov_TN_reg[ot][0][reg]();
4280
            gen_op_mov_TN_reg[ot][1][rm]();
4281
            gen_op_mov_reg_T0[ot][rm]();
4282
            gen_op_mov_reg_T1[ot][reg]();
4283
        } else {
4284
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4285
            gen_op_mov_TN_reg[ot][0][reg]();
4286
            /* for xchg, lock is implicit */
4287
            if (!(prefixes & PREFIX_LOCK))
4288
                gen_op_lock();
4289
            gen_op_ld_T1_A0[ot + s->mem_index]();
4290
            gen_op_st_T0_A0[ot + s->mem_index]();
4291
            if (!(prefixes & PREFIX_LOCK))
4292
                gen_op_unlock();
4293
            gen_op_mov_reg_T1[ot][reg]();
4294
        }
4295
        break;
4296
    case 0xc4: /* les Gv */
4297
        if (CODE64(s))
4298
            goto illegal_op;
4299
        op = R_ES;
4300
        goto do_lxx;
4301
    case 0xc5: /* lds Gv */
4302
        if (CODE64(s))
4303
            goto illegal_op;
4304
        op = R_DS;
4305
        goto do_lxx;
4306
    case 0x1b2: /* lss Gv */
4307
        op = R_SS;
4308
        goto do_lxx;
4309
    case 0x1b4: /* lfs Gv */
4310
        op = R_FS;
4311
        goto do_lxx;
4312
    case 0x1b5: /* lgs Gv */
4313
        op = R_GS;
4314
    do_lxx:
4315
        ot = dflag ? OT_LONG : OT_WORD;
4316
        modrm = ldub_code(s->pc++);
4317
        reg = ((modrm >> 3) & 7) | rex_r;
4318
        mod = (modrm >> 6) & 3;
4319
        if (mod == 3)
4320
            goto illegal_op;
4321
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4322
        gen_op_ld_T1_A0[ot + s->mem_index]();
4323
        gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4324
        /* load the segment first to handle exceptions properly */
4325
        gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
4326
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4327
        /* then put the data */
4328
        gen_op_mov_reg_T1[ot][reg]();
4329
        if (s->is_jmp) {
4330
            gen_jmp_im(s->pc - s->cs_base);
4331
            gen_eob(s);
4332
        }
4333
        break;
4334

    
4335
        /************************/
4336
        /* shifts */
4337
    case 0xc0:
4338
    case 0xc1:
4339
        /* shift Ev,Ib */
4340
        shift = 2;
4341
    grp2:
4342
        {
4343
            if ((b & 1) == 0)
4344
                ot = OT_BYTE;
4345
            else
4346
                ot = dflag + OT_WORD;
4347

    
4348
            modrm = ldub_code(s->pc++);
4349
            mod = (modrm >> 6) & 3;
4350
            op = (modrm >> 3) & 7;
4351

    
4352
            if (mod != 3) {
4353
                if (shift == 2) {
4354
                    s->rip_offset = 1;
4355
                }
4356
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4357
                opreg = OR_TMP0;
4358
            } else {
4359
                opreg = (modrm & 7) | REX_B(s);
4360
            }
4361

    
4362
            /* simpler op */
4363
            if (shift == 0) {
4364
                gen_shift(s, op, ot, opreg, OR_ECX);
4365
            } else {
4366
                if (shift == 2) {
4367
                    shift = ldub_code(s->pc++);
4368
                }
4369
                gen_shifti(s, op, ot, opreg, shift);
4370
            }
4371
        }
4372
        break;
4373
    case 0xd0:
4374
    case 0xd1:
4375
        /* shift Ev,1 */
4376
        shift = 1;
4377
        goto grp2;
4378
    case 0xd2:
4379
    case 0xd3:
4380
        /* shift Ev,cl */
4381
        shift = 0;
4382
        goto grp2;
4383

    
4384
    case 0x1a4: /* shld imm */
4385
        op = 0;
4386
        shift = 1;
4387
        goto do_shiftd;
4388
    case 0x1a5: /* shld cl */
4389
        op = 0;
4390
        shift = 0;
4391
        goto do_shiftd;
4392
    case 0x1ac: /* shrd imm */
4393
        op = 1;
4394
        shift = 1;
4395
        goto do_shiftd;
4396
    case 0x1ad: /* shrd cl */
4397
        op = 1;
4398
        shift = 0;
4399
    do_shiftd:
4400
        ot = dflag + OT_WORD;
4401
        modrm = ldub_code(s->pc++);
4402
        mod = (modrm >> 6) & 3;
4403
        rm = (modrm & 7) | REX_B(s);
4404
        reg = ((modrm >> 3) & 7) | rex_r;
4405

    
4406
        if (mod != 3) {
4407
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4408
            gen_op_ld_T0_A0[ot + s->mem_index]();
4409
        } else {
4410
            gen_op_mov_TN_reg[ot][0][rm]();
4411
        }
4412
        gen_op_mov_TN_reg[ot][1][reg]();
4413

    
4414
        if (shift) {
4415
            val = ldub_code(s->pc++);
4416
            if (ot == OT_QUAD)
4417
                val &= 0x3f;
4418
            else
4419
                val &= 0x1f;
4420
            if (val) {
4421
                if (mod == 3)
4422
                    gen_op_shiftd_T0_T1_im_cc[ot][op](val);
4423
                else
4424
                    gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
4425
                if (op == 0 && ot != OT_WORD)
4426
                    s->cc_op = CC_OP_SHLB + ot;
4427
                else
4428
                    s->cc_op = CC_OP_SARB + ot;
4429
            }
4430
        } else {
4431
            if (s->cc_op != CC_OP_DYNAMIC)
4432
                gen_op_set_cc_op(s->cc_op);
4433
            if (mod == 3)
4434
                gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
4435
            else
4436
                gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
4437
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4438
        }
4439
        if (mod == 3) {
4440
            gen_op_mov_reg_T0[ot][rm]();
4441
        }
4442
        break;
4443

    
4444
        /************************/
4445
        /* floats */
4446
    case 0xd8 ... 0xdf:
4447
        if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4448
            /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4449
            /* XXX: what to do if illegal op ? */
4450
            gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4451
            break;
4452
        }
4453
        modrm = ldub_code(s->pc++);
4454
        mod = (modrm >> 6) & 3;
4455
        rm = modrm & 7;
4456
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4457
        if (mod != 3) {
4458
            /* memory op */
4459
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4460
            switch(op) {
4461
            case 0x00 ... 0x07: /* fxxxs */
4462
            case 0x10 ... 0x17: /* fixxxl */
4463
            case 0x20 ... 0x27: /* fxxxl */
4464
            case 0x30 ... 0x37: /* fixxx */
4465
                {
4466
                    int op1;
4467
                    op1 = op & 7;
4468

    
4469
                    switch(op >> 4) {
4470
                    case 0:
4471
                        gen_op_flds_FT0_A0();
4472
                        break;
4473
                    case 1:
4474
                        gen_op_fildl_FT0_A0();
4475
                        break;
4476
                    case 2:
4477
                        gen_op_fldl_FT0_A0();
4478
                        break;
4479
                    case 3:
4480
                    default:
4481
                        gen_op_fild_FT0_A0();
4482
                        break;
4483
                    }
4484

    
4485
                    gen_op_fp_arith_ST0_FT0[op1]();
4486
                    if (op1 == 3) {
4487
                        /* fcomp needs pop */
4488
                        gen_op_fpop();
4489
                    }
4490
                }
4491
                break;
4492
            case 0x08: /* flds */
4493
            case 0x0a: /* fsts */
4494
            case 0x0b: /* fstps */
4495
            case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
4496
            case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
4497
            case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
4498
                switch(op & 7) {
4499
                case 0:
4500
                    switch(op >> 4) {
4501
                    case 0:
4502
                        gen_op_flds_ST0_A0();
4503
                        break;
4504
                    case 1:
4505
                        gen_op_fildl_ST0_A0();
4506
                        break;
4507
                    case 2:
4508
                        gen_op_fldl_ST0_A0();
4509
                        break;
4510
                    case 3:
4511
                    default:
4512
                        gen_op_fild_ST0_A0();
4513
                        break;
4514
                    }
4515
                    break;
4516
                case 1:
4517
                    switch(op >> 4) {
4518
                    case 1:
4519
                        gen_op_fisttl_ST0_A0();
4520
                        break;
4521
                    case 2:
4522
                        gen_op_fisttll_ST0_A0();
4523
                        break;
4524
                    case 3:
4525
                    default:
4526
                        gen_op_fistt_ST0_A0();
4527
                    }
4528
                    gen_op_fpop();
4529
                    break;
4530
                default:
4531
                    switch(op >> 4) {
4532
                    case 0:
4533
                        gen_op_fsts_ST0_A0();
4534
                        break;
4535
                    case 1:
4536
                        gen_op_fistl_ST0_A0();
4537
                        break;
4538
                    case 2:
4539
                        gen_op_fstl_ST0_A0();
4540
                        break;
4541
                    case 3:
4542
                    default:
4543
                        gen_op_fist_ST0_A0();
4544
                        break;
4545
                    }
4546
                    if ((op & 7) == 3)
4547
                        gen_op_fpop();
4548
                    break;
4549
                }
4550
                break;
4551
            case 0x0c: /* fldenv mem */
4552
                gen_op_fldenv_A0(s->dflag);
4553
                break;
4554
            case 0x0d: /* fldcw mem */
4555
                gen_op_fldcw_A0();
4556
                break;
4557
            case 0x0e: /* fnstenv mem */
4558
                gen_op_fnstenv_A0(s->dflag);
4559
                break;
4560
            case 0x0f: /* fnstcw mem */
4561
                gen_op_fnstcw_A0();
4562
                break;
4563
            case 0x1d: /* fldt mem */
4564
                gen_op_fldt_ST0_A0();
4565
                break;
4566
            case 0x1f: /* fstpt mem */
4567
                gen_op_fstt_ST0_A0();
4568
                gen_op_fpop();
4569
                break;
4570
            case 0x2c: /* frstor mem */
4571
                gen_op_frstor_A0(s->dflag);
4572
                break;
4573
            case 0x2e: /* fnsave mem */
4574
                gen_op_fnsave_A0(s->dflag);
4575
                break;
4576
            case 0x2f: /* fnstsw mem */
4577
                gen_op_fnstsw_A0();
4578
                break;
4579
            case 0x3c: /* fbld */
4580
                gen_op_fbld_ST0_A0();
4581
                break;
4582
            case 0x3e: /* fbstp */
4583
                gen_op_fbst_ST0_A0();
4584
                gen_op_fpop();
4585
                break;
4586
            case 0x3d: /* fildll */
4587
                gen_op_fildll_ST0_A0();
4588
                break;
4589
            case 0x3f: /* fistpll */
4590
                gen_op_fistll_ST0_A0();
4591
                gen_op_fpop();
4592
                break;
4593
            default:
4594
                goto illegal_op;
4595
            }
4596
        } else {
4597
            /* register float ops */
4598
            opreg = rm;
4599

    
4600
            switch(op) {
4601
            case 0x08: /* fld sti */
4602
                gen_op_fpush();
4603
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
4604
                break;
4605
            case 0x09: /* fxchg sti */
4606
            case 0x29: /* fxchg4 sti, undocumented op */
4607
            case 0x39: /* fxchg7 sti, undocumented op */
4608
                gen_op_fxchg_ST0_STN(opreg);
4609
                break;
4610
            case 0x0a: /* grp d9/2 */
4611
                switch(rm) {
4612
                case 0: /* fnop */
4613
                    /* check exceptions (FreeBSD FPU probe) */
4614
                    if (s->cc_op != CC_OP_DYNAMIC)
4615
                        gen_op_set_cc_op(s->cc_op);
4616
                    gen_jmp_im(pc_start - s->cs_base);
4617
                    gen_op_fwait();
4618
                    break;
4619
                default:
4620
                    goto illegal_op;
4621
                }
4622
                break;
4623
            case 0x0c: /* grp d9/4 */
4624
                switch(rm) {
4625
                case 0: /* fchs */
4626
                    gen_op_fchs_ST0();
4627
                    break;
4628
                case 1: /* fabs */
4629
                    gen_op_fabs_ST0();
4630
                    break;
4631
                case 4: /* ftst */
4632
                    gen_op_fldz_FT0();
4633
                    gen_op_fcom_ST0_FT0();
4634
                    break;
4635
                case 5: /* fxam */
4636
                    gen_op_fxam_ST0();
4637
                    break;
4638
                default:
4639
                    goto illegal_op;
4640
                }
4641
                break;
4642
            case 0x0d: /* grp d9/5 */
4643
                {
4644
                    switch(rm) {
4645
                    case 0:
4646
                        gen_op_fpush();
4647
                        gen_op_fld1_ST0();
4648
                        break;
4649
                    case 1:
4650
                        gen_op_fpush();
4651
                        gen_op_fldl2t_ST0();
4652
                        break;
4653
                    case 2:
4654
                        gen_op_fpush();
4655
                        gen_op_fldl2e_ST0();
4656
                        break;
4657
                    case 3:
4658
                        gen_op_fpush();
4659
                        gen_op_fldpi_ST0();
4660
                        break;
4661
                    case 4:
4662
                        gen_op_fpush();
4663
                        gen_op_fldlg2_ST0();
4664
                        break;
4665
                    case 5:
4666
                        gen_op_fpush();
4667
                        gen_op_fldln2_ST0();
4668
                        break;
4669
                    case 6:
4670
                        gen_op_fpush();
4671
                        gen_op_fldz_ST0();
4672
                        break;
4673
                    default:
4674
                        goto illegal_op;
4675
                    }
4676
                }
4677
                break;
4678
            case 0x0e: /* grp d9/6 */
4679
                switch(rm) {
4680
                case 0: /* f2xm1 */
4681
                    gen_op_f2xm1();
4682
                    break;
4683
                case 1: /* fyl2x */
4684
                    gen_op_fyl2x();
4685
                    break;
4686
                case 2: /* fptan */
4687
                    gen_op_fptan();
4688
                    break;
4689
                case 3: /* fpatan */
4690
                    gen_op_fpatan();
4691
                    break;
4692
                case 4: /* fxtract */
4693
                    gen_op_fxtract();
4694
                    break;
4695
                case 5: /* fprem1 */
4696
                    gen_op_fprem1();
4697
                    break;
4698
                case 6: /* fdecstp */
4699
                    gen_op_fdecstp();
4700
                    break;
4701
                default:
4702
                case 7: /* fincstp */
4703
                    gen_op_fincstp();
4704
                    break;
4705
                }
4706
                break;
4707
            case 0x0f: /* grp d9/7 */
4708
                switch(rm) {
4709
                case 0: /* fprem */
4710
                    gen_op_fprem();
4711
                    break;
4712
                case 1: /* fyl2xp1 */
4713
                    gen_op_fyl2xp1();
4714
                    break;
4715
                case 2: /* fsqrt */
4716
                    gen_op_fsqrt();
4717
                    break;
4718
                case 3: /* fsincos */
4719
                    gen_op_fsincos();
4720
                    break;
4721
                case 5: /* fscale */
4722
                    gen_op_fscale();
4723
                    break;
4724
                case 4: /* frndint */
4725
                    gen_op_frndint();
4726
                    break;
4727
                case 6: /* fsin */
4728
                    gen_op_fsin();
4729
                    break;
4730
                default:
4731
                case 7: /* fcos */
4732
                    gen_op_fcos();
4733
                    break;
4734
                }
4735
                break;
4736
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4737
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4738
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4739
                {
4740
                    int op1;
4741

    
4742
                    op1 = op & 7;
4743
                    if (op >= 0x20) {
4744
                        gen_op_fp_arith_STN_ST0[op1](opreg);
4745
                        if (op >= 0x30)
4746
                            gen_op_fpop();
4747
                    } else {
4748
                        gen_op_fmov_FT0_STN(opreg);
4749
                        gen_op_fp_arith_ST0_FT0[op1]();
4750
                    }
4751
                }
4752
                break;
4753
            case 0x02: /* fcom */
4754
            case 0x22: /* fcom2, undocumented op */
4755
                gen_op_fmov_FT0_STN(opreg);
4756
                gen_op_fcom_ST0_FT0();
4757
                break;
4758
            case 0x03: /* fcomp */
4759
            case 0x23: /* fcomp3, undocumented op */
4760
            case 0x32: /* fcomp5, undocumented op */
4761
                gen_op_fmov_FT0_STN(opreg);
4762
                gen_op_fcom_ST0_FT0();
4763
                gen_op_fpop();
4764
                break;
4765
            case 0x15: /* da/5 */
4766
                switch(rm) {
4767
                case 1: /* fucompp */
4768
                    gen_op_fmov_FT0_STN(1);
4769
                    gen_op_fucom_ST0_FT0();
4770
                    gen_op_fpop();
4771
                    gen_op_fpop();
4772
                    break;
4773
                default:
4774
                    goto illegal_op;
4775
                }
4776
                break;
4777
            case 0x1c:
4778
                switch(rm) {
4779
                case 0: /* feni (287 only, just do nop here) */
4780
                    break;
4781
                case 1: /* fdisi (287 only, just do nop here) */
4782
                    break;
4783
                case 2: /* fclex */
4784
                    gen_op_fclex();
4785
                    break;
4786
                case 3: /* fninit */
4787
                    gen_op_fninit();
4788
                    break;
4789
                case 4: /* fsetpm (287 only, just do nop here) */
4790
                    break;
4791
                default:
4792
                    goto illegal_op;
4793
                }
4794
                break;
4795
            case 0x1d: /* fucomi */
4796
                if (s->cc_op != CC_OP_DYNAMIC)
4797
                    gen_op_set_cc_op(s->cc_op);
4798
                gen_op_fmov_FT0_STN(opreg);
4799
                gen_op_fucomi_ST0_FT0();
4800
                s->cc_op = CC_OP_EFLAGS;
4801
                break;
4802
            case 0x1e: /* fcomi */
4803
                if (s->cc_op != CC_OP_DYNAMIC)
4804
                    gen_op_set_cc_op(s->cc_op);
4805
                gen_op_fmov_FT0_STN(opreg);
4806
                gen_op_fcomi_ST0_FT0();
4807
                s->cc_op = CC_OP_EFLAGS;
4808
                break;
4809
            case 0x28: /* ffree sti */
4810
                gen_op_ffree_STN(opreg);
4811
                break;
4812
            case 0x2a: /* fst sti */
4813
                gen_op_fmov_STN_ST0(opreg);
4814
                break;
4815
            case 0x2b: /* fstp sti */
4816
            case 0x0b: /* fstp1 sti, undocumented op */
4817
            case 0x3a: /* fstp8 sti, undocumented op */
4818
            case 0x3b: /* fstp9 sti, undocumented op */
4819
                gen_op_fmov_STN_ST0(opreg);
4820
                gen_op_fpop();
4821
                break;
4822
            case 0x2c: /* fucom st(i) */
4823
                gen_op_fmov_FT0_STN(opreg);
4824
                gen_op_fucom_ST0_FT0();
4825
                break;
4826
            case 0x2d: /* fucomp st(i) */
4827
                gen_op_fmov_FT0_STN(opreg);
4828
                gen_op_fucom_ST0_FT0();
4829
                gen_op_fpop();
4830
                break;
4831
            case 0x33: /* de/3 */
4832
                switch(rm) {
4833
                case 1: /* fcompp */
4834
                    gen_op_fmov_FT0_STN(1);
4835
                    gen_op_fcom_ST0_FT0();
4836
                    gen_op_fpop();
4837
                    gen_op_fpop();
4838
                    break;
4839
                default:
4840
                    goto illegal_op;
4841
                }
4842
                break;
4843
            case 0x38: /* ffreep sti, undocumented op */
4844
                gen_op_ffree_STN(opreg);
4845
                gen_op_fpop();
4846
                break;
4847
            case 0x3c: /* df/4 */
4848
                switch(rm) {
4849
                case 0:
4850
                    gen_op_fnstsw_EAX();
4851
                    break;
4852
                default:
4853
                    goto illegal_op;
4854
                }
4855
                break;
4856
            case 0x3d: /* fucomip */
4857
                if (s->cc_op != CC_OP_DYNAMIC)
4858
                    gen_op_set_cc_op(s->cc_op);
4859
                gen_op_fmov_FT0_STN(opreg);
4860
                gen_op_fucomi_ST0_FT0();
4861
                gen_op_fpop();
4862
                s->cc_op = CC_OP_EFLAGS;
4863
                break;
4864
            case 0x3e: /* fcomip */
4865
                if (s->cc_op != CC_OP_DYNAMIC)
4866
                    gen_op_set_cc_op(s->cc_op);
4867
                gen_op_fmov_FT0_STN(opreg);
4868
                gen_op_fcomi_ST0_FT0();
4869
                gen_op_fpop();
4870
                s->cc_op = CC_OP_EFLAGS;
4871
                break;
4872
            case 0x10 ... 0x13: /* fcmovxx */
4873
            case 0x18 ... 0x1b:
4874
                {
4875
                    int op1;
4876
                    const static uint8_t fcmov_cc[8] = {
4877
                        (JCC_B << 1),
4878
                        (JCC_Z << 1),
4879
                        (JCC_BE << 1),
4880
                        (JCC_P << 1),
4881
                    };
4882
                    op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4883
                    gen_setcc(s, op1);
4884
                    gen_op_fcmov_ST0_STN_T0(opreg);
4885
                }
4886
                break;
4887
            default:
4888
                goto illegal_op;
4889
            }
4890
        }
4891
#ifdef USE_CODE_COPY
4892
        s->tb->cflags |= CF_TB_FP_USED;
4893
#endif
4894
        break;
4895
        /************************/
4896
        /* string ops */
4897

    
4898
    case 0xa4: /* movsS */
4899
    case 0xa5:
4900
        if ((b & 1) == 0)
4901
            ot = OT_BYTE;
4902
        else
4903
            ot = dflag + OT_WORD;
4904

    
4905
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4906
            gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4907
        } else {
4908
            gen_movs(s, ot);
4909
        }
4910
        break;
4911

    
4912
    case 0xaa: /* stosS */
4913
    case 0xab:
4914
        if ((b & 1) == 0)
4915
            ot = OT_BYTE;
4916
        else
4917
            ot = dflag + OT_WORD;
4918

    
4919
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4920
            gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4921
        } else {
4922
            gen_stos(s, ot);
4923
        }
4924
        break;
4925
    case 0xac: /* lodsS */
4926
    case 0xad:
4927
        if ((b & 1) == 0)
4928
            ot = OT_BYTE;
4929
        else
4930
            ot = dflag + OT_WORD;
4931
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4932
            gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4933
        } else {
4934
            gen_lods(s, ot);
4935
        }
4936
        break;
4937
    case 0xae: /* scasS */
4938
    case 0xaf:
4939
        if ((b & 1) == 0)
4940
            ot = OT_BYTE;
4941
        else
4942
            ot = dflag + OT_WORD;
4943
        if (prefixes & PREFIX_REPNZ) {
4944
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4945
        } else if (prefixes & PREFIX_REPZ) {
4946
            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4947
        } else {
4948
            gen_scas(s, ot);
4949
            s->cc_op = CC_OP_SUBB + ot;
4950
        }
4951
        break;
4952

    
4953
    case 0xa6: /* cmpsS */
4954
    case 0xa7:
4955
        if ((b & 1) == 0)
4956
            ot = OT_BYTE;
4957
        else
4958
            ot = dflag + OT_WORD;
4959
        if (prefixes & PREFIX_REPNZ) {
4960
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4961
        } else if (prefixes & PREFIX_REPZ) {
4962
            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4963
        } else {
4964
            gen_cmps(s, ot);
4965
            s->cc_op = CC_OP_SUBB + ot;
4966
        }
4967
        break;
4968
    case 0x6c: /* insS */
4969
    case 0x6d:
4970
        if ((b & 1) == 0)
4971
            ot = OT_BYTE;
4972
        else
4973
            ot = dflag ? OT_LONG : OT_WORD;
4974
        gen_check_io(s, ot, 1, pc_start - s->cs_base);
4975
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4976
        gen_op_andl_T0_ffff();
4977
        if (gen_svm_check_io(s, pc_start,
4978
                             SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
4979
                             svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
4980
            break;
4981
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4982
            gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4983
        } else {
4984
            gen_ins(s, ot);
4985
        }
4986
        break;
4987
    case 0x6e: /* outsS */
4988
    case 0x6f:
4989
        if ((b & 1) == 0)
4990
            ot = OT_BYTE;
4991
        else
4992
            ot = dflag ? OT_LONG : OT_WORD;
4993
        gen_check_io(s, ot, 1, pc_start - s->cs_base);
4994
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4995
        gen_op_andl_T0_ffff();
4996
        if (gen_svm_check_io(s, pc_start,
4997
                             (1 << (4+ot)) | svm_is_rep(prefixes) |