Statistics
| Branch: | Revision:

root / translate-i386.c @ 4021dab0

History | View | Annotate | Download (126.6 kB)

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

    
29
#include "cpu-i386.h"
30
#include "exec.h"
31
#include "disas.h"
32

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

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

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

    
68
/* i386 arith/logic operations */
69
enum {
70
    OP_ADDL, 
71
    OP_ORL, 
72
    OP_ADCL, 
73
    OP_SBBL,
74
    OP_ANDL, 
75
    OP_SUBL, 
76
    OP_XORL, 
77
    OP_CMPL,
78
};
79

    
80
/* i386 shift ops */
81
enum {
82
    OP_ROL, 
83
    OP_ROR, 
84
    OP_RCL, 
85
    OP_RCR, 
86
    OP_SHL, 
87
    OP_SHR, 
88
    OP_SHL1, /* undocumented */
89
    OP_SAR = 7,
90
};
91

    
92
enum {
93
#define DEF(s, n, copy_size) INDEX_op_ ## s,
94
#include "opc-i386.h"
95
#undef DEF
96
    NB_OPS,
97
};
98

    
99
#include "gen-op-i386.h"
100

    
101
/* operand size */
102
enum {
103
    OT_BYTE = 0,
104
    OT_WORD,
105
    OT_LONG, 
106
    OT_QUAD,
107
};
108

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

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

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

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

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

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

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

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

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

    
378
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
379
    [OT_BYTE] = {
380
        gen_op_adcb_T0_T1_cc,
381
        gen_op_sbbb_T0_T1_cc,
382
    },
383
    [OT_WORD] = {
384
        gen_op_adcw_T0_T1_cc,
385
        gen_op_sbbw_T0_T1_cc,
386
    },
387
    [OT_LONG] = {
388
        gen_op_adcl_T0_T1_cc,
389
        gen_op_sbbl_T0_T1_cc,
390
    },
391
};
392

    
393
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3][2] = {
394
    [OT_BYTE] = {
395
        gen_op_adcb_mem_T0_T1_cc,
396
        gen_op_sbbb_mem_T0_T1_cc,
397
    },
398
    [OT_WORD] = {
399
        gen_op_adcw_mem_T0_T1_cc,
400
        gen_op_sbbw_mem_T0_T1_cc,
401
    },
402
    [OT_LONG] = {
403
        gen_op_adcl_mem_T0_T1_cc,
404
        gen_op_sbbl_mem_T0_T1_cc,
405
    },
406
};
407

    
408
static const int cc_op_arithb[8] = {
409
    CC_OP_ADDB,
410
    CC_OP_LOGICB,
411
    CC_OP_ADDB,
412
    CC_OP_SUBB,
413
    CC_OP_LOGICB,
414
    CC_OP_SUBB,
415
    CC_OP_LOGICB,
416
    CC_OP_SUBB,
417
};
418

    
419
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
420
    gen_op_cmpxchgb_T0_T1_EAX_cc,
421
    gen_op_cmpxchgw_T0_T1_EAX_cc,
422
    gen_op_cmpxchgl_T0_T1_EAX_cc,
423
};
424

    
425
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3] = {
426
    gen_op_cmpxchgb_mem_T0_T1_EAX_cc,
427
    gen_op_cmpxchgw_mem_T0_T1_EAX_cc,
428
    gen_op_cmpxchgl_mem_T0_T1_EAX_cc,
429
};
430

    
431
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
432
    [OT_BYTE] = {
433
        gen_op_rolb_T0_T1_cc,
434
        gen_op_rorb_T0_T1_cc,
435
        gen_op_rclb_T0_T1_cc,
436
        gen_op_rcrb_T0_T1_cc,
437
        gen_op_shlb_T0_T1_cc,
438
        gen_op_shrb_T0_T1_cc,
439
        gen_op_shlb_T0_T1_cc,
440
        gen_op_sarb_T0_T1_cc,
441
    },
442
    [OT_WORD] = {
443
        gen_op_rolw_T0_T1_cc,
444
        gen_op_rorw_T0_T1_cc,
445
        gen_op_rclw_T0_T1_cc,
446
        gen_op_rcrw_T0_T1_cc,
447
        gen_op_shlw_T0_T1_cc,
448
        gen_op_shrw_T0_T1_cc,
449
        gen_op_shlw_T0_T1_cc,
450
        gen_op_sarw_T0_T1_cc,
451
    },
452
    [OT_LONG] = {
453
        gen_op_roll_T0_T1_cc,
454
        gen_op_rorl_T0_T1_cc,
455
        gen_op_rcll_T0_T1_cc,
456
        gen_op_rcrl_T0_T1_cc,
457
        gen_op_shll_T0_T1_cc,
458
        gen_op_shrl_T0_T1_cc,
459
        gen_op_shll_T0_T1_cc,
460
        gen_op_sarl_T0_T1_cc,
461
    },
462
};
463

    
464
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3][8] = {
465
    [OT_BYTE] = {
466
        gen_op_rolb_mem_T0_T1_cc,
467
        gen_op_rorb_mem_T0_T1_cc,
468
        gen_op_rclb_mem_T0_T1_cc,
469
        gen_op_rcrb_mem_T0_T1_cc,
470
        gen_op_shlb_mem_T0_T1_cc,
471
        gen_op_shrb_mem_T0_T1_cc,
472
        gen_op_shlb_mem_T0_T1_cc,
473
        gen_op_sarb_mem_T0_T1_cc,
474
    },
475
    [OT_WORD] = {
476
        gen_op_rolw_mem_T0_T1_cc,
477
        gen_op_rorw_mem_T0_T1_cc,
478
        gen_op_rclw_mem_T0_T1_cc,
479
        gen_op_rcrw_mem_T0_T1_cc,
480
        gen_op_shlw_mem_T0_T1_cc,
481
        gen_op_shrw_mem_T0_T1_cc,
482
        gen_op_shlw_mem_T0_T1_cc,
483
        gen_op_sarw_mem_T0_T1_cc,
484
    },
485
    [OT_LONG] = {
486
        gen_op_roll_mem_T0_T1_cc,
487
        gen_op_rorl_mem_T0_T1_cc,
488
        gen_op_rcll_mem_T0_T1_cc,
489
        gen_op_rcrl_mem_T0_T1_cc,
490
        gen_op_shll_mem_T0_T1_cc,
491
        gen_op_shrl_mem_T0_T1_cc,
492
        gen_op_shll_mem_T0_T1_cc,
493
        gen_op_sarl_mem_T0_T1_cc,
494
    },
495
};
496

    
497
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
498
    [0] = {
499
        gen_op_shldw_T0_T1_im_cc,
500
        gen_op_shrdw_T0_T1_im_cc,
501
    },
502
    [1] = {
503
        gen_op_shldl_T0_T1_im_cc,
504
        gen_op_shrdl_T0_T1_im_cc,
505
    },
506
};
507

    
508
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
509
    [0] = {
510
        gen_op_shldw_T0_T1_ECX_cc,
511
        gen_op_shrdw_T0_T1_ECX_cc,
512
    },
513
    [1] = {
514
        gen_op_shldl_T0_T1_ECX_cc,
515
        gen_op_shrdl_T0_T1_ECX_cc,
516
    },
517
};
518

    
519
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[2][2] = {
520
    [0] = {
521
        gen_op_shldw_mem_T0_T1_im_cc,
522
        gen_op_shrdw_mem_T0_T1_im_cc,
523
    },
524
    [1] = {
525
        gen_op_shldl_mem_T0_T1_im_cc,
526
        gen_op_shrdl_mem_T0_T1_im_cc,
527
    },
528
};
529

    
530
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[2][2] = {
531
    [0] = {
532
        gen_op_shldw_mem_T0_T1_ECX_cc,
533
        gen_op_shrdw_mem_T0_T1_ECX_cc,
534
    },
535
    [1] = {
536
        gen_op_shldl_mem_T0_T1_ECX_cc,
537
        gen_op_shrdl_mem_T0_T1_ECX_cc,
538
    },
539
};
540

    
541
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
542
    [0] = {
543
        gen_op_btw_T0_T1_cc,
544
        gen_op_btsw_T0_T1_cc,
545
        gen_op_btrw_T0_T1_cc,
546
        gen_op_btcw_T0_T1_cc,
547
    },
548
    [1] = {
549
        gen_op_btl_T0_T1_cc,
550
        gen_op_btsl_T0_T1_cc,
551
        gen_op_btrl_T0_T1_cc,
552
        gen_op_btcl_T0_T1_cc,
553
    },
554
};
555

    
556
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
557
    [0] = {
558
        gen_op_bsfw_T0_cc,
559
        gen_op_bsrw_T0_cc,
560
    },
561
    [1] = {
562
        gen_op_bsfl_T0_cc,
563
        gen_op_bsrl_T0_cc,
564
    },
565
};
566

    
567
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = {
568
    gen_op_ldsb_T0_A0,
569
    gen_op_ldsw_T0_A0,
570
    NULL,
571

    
572
    gen_op_ldsb_kernel_T0_A0,
573
    gen_op_ldsw_kernel_T0_A0,
574
    NULL,
575

    
576
    gen_op_ldsb_user_T0_A0,
577
    gen_op_ldsw_user_T0_A0,
578
    NULL,
579
};
580

    
581
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = {
582
    gen_op_ldub_T0_A0,
583
    gen_op_lduw_T0_A0,
584
    NULL,
585

    
586
    gen_op_ldub_kernel_T0_A0,
587
    gen_op_lduw_kernel_T0_A0,
588
    NULL,
589

    
590
    gen_op_ldub_user_T0_A0,
591
    gen_op_lduw_user_T0_A0,
592
    NULL,
593
};
594

    
595
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
596
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = {
597
    gen_op_ldub_T0_A0,
598
    gen_op_lduw_T0_A0,
599
    gen_op_ldl_T0_A0,
600

    
601
    gen_op_ldub_kernel_T0_A0,
602
    gen_op_lduw_kernel_T0_A0,
603
    gen_op_ldl_kernel_T0_A0,
604

    
605
    gen_op_ldub_user_T0_A0,
606
    gen_op_lduw_user_T0_A0,
607
    gen_op_ldl_user_T0_A0,
608
};
609

    
610
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = {
611
    gen_op_ldub_T1_A0,
612
    gen_op_lduw_T1_A0,
613
    gen_op_ldl_T1_A0,
614

    
615
    gen_op_ldub_kernel_T1_A0,
616
    gen_op_lduw_kernel_T1_A0,
617
    gen_op_ldl_kernel_T1_A0,
618

    
619
    gen_op_ldub_user_T1_A0,
620
    gen_op_lduw_user_T1_A0,
621
    gen_op_ldl_user_T1_A0,
622
};
623

    
624
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
625
    gen_op_stb_T0_A0,
626
    gen_op_stw_T0_A0,
627
    gen_op_stl_T0_A0,
628

    
629
    gen_op_stb_kernel_T0_A0,
630
    gen_op_stw_kernel_T0_A0,
631
    gen_op_stl_kernel_T0_A0,
632

    
633
    gen_op_stb_user_T0_A0,
634
    gen_op_stw_user_T0_A0,
635
    gen_op_stl_user_T0_A0,
636
};
637

    
638
/* the _a32 and _a16 string operations use A0 as the base register. */
639

    
640
#define STRINGOP_NB 9
641

    
642
#define STRINGOP(x) \
643
    gen_op_ ## x ## b_fast, \
644
    gen_op_ ## x ## w_fast, \
645
    gen_op_ ## x ## l_fast, \
646
    gen_op_ ## x ## b_a32, \
647
    gen_op_ ## x ## w_a32, \
648
    gen_op_ ## x ## l_a32, \
649
    gen_op_ ## x ## b_a16, \
650
    gen_op_ ## x ## w_a16, \
651
    gen_op_ ## x ## l_a16,
652
     
653
static GenOpFunc *gen_op_scas[STRINGOP_NB * 3] = {
654
    STRINGOP(repz_scas)
655
    STRINGOP(repnz_scas)
656
};
657

    
658
static GenOpFunc *gen_op_cmps[STRINGOP_NB * 3] = {
659
    STRINGOP(repz_cmps)
660
    STRINGOP(repnz_cmps)
661
};
662

    
663
static inline void gen_string_movl_A0_ESI(DisasContext *s)
664
{
665
    int override;
666

    
667
    override = s->override;
668
    if (s->aflag) {
669
        /* 32 bit address */
670
        if (s->addseg && override < 0)
671
            override = R_DS;
672
        if (override >= 0) {
673
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
674
            gen_op_addl_A0_reg_sN[0][R_ESI]();
675
        } else {
676
            gen_op_movl_A0_reg[R_ESI]();
677
        }
678
    } else {
679
        /* 16 address, always override */
680
        if (override < 0)
681
            override = R_DS;
682
        gen_op_movl_A0_reg[R_ESI]();
683
        gen_op_andl_A0_ffff();
684
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
685
    }
686
}
687

    
688
static inline void gen_string_movl_A0_EDI(DisasContext *s)
689
{
690
    if (s->aflag) {
691
        if (s->addseg) {
692
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
693
            gen_op_addl_A0_reg_sN[0][R_EDI]();
694
        } else {
695
            gen_op_movl_A0_reg[R_EDI]();
696
        }
697
    } else {
698
        gen_op_movl_A0_reg[R_EDI]();
699
        gen_op_andl_A0_ffff();
700
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
701
    }
702
}
703

    
704
static GenOpFunc *gen_op_movl_T0_Dshift[3] = {
705
    gen_op_movl_T0_Dshiftb,
706
    gen_op_movl_T0_Dshiftw,
707
    gen_op_movl_T0_Dshiftl,
708
};
709

    
710
static GenOpFunc2 *gen_op_jz_ecx[2] = {
711
    gen_op_jz_ecxw,
712
    gen_op_jz_ecxl,
713
};
714
    
715
static GenOpFunc *gen_op_dec_ECX[2] = {
716
    gen_op_decw_ECX,
717
    gen_op_decl_ECX,
718
};
719

    
720
static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = {
721
    {
722
        gen_op_string_jnz_subb,
723
        gen_op_string_jnz_subw,
724
        gen_op_string_jnz_subl,
725
    },
726
    {
727
        gen_op_string_jz_subb,
728
        gen_op_string_jz_subw,
729
        gen_op_string_jz_subl,
730
    },
731
};
732

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

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

    
745
static inline void gen_movs(DisasContext *s, int ot)
746
{
747
    gen_string_movl_A0_ESI(s);
748
    gen_op_ld_T0_A0[ot + s->mem_index]();
749
    gen_string_movl_A0_EDI(s);
750
    gen_op_st_T0_A0[ot + s->mem_index]();
751
    gen_op_movl_T0_Dshift[ot]();
752
    if (s->aflag) {
753
        gen_op_addl_ESI_T0();
754
        gen_op_addl_EDI_T0();
755
    } else {
756
        gen_op_addw_ESI_T0();
757
        gen_op_addw_EDI_T0();
758
    }
759
}
760

    
761
/* same method as Valgrind : we generate jumps to current or next
762
   instruction */
763
static inline void gen_repz_movs(DisasContext *s, int ot, 
764
                                 unsigned int cur_eip, unsigned int next_eip)
765
{
766
    if (s->cc_op != CC_OP_DYNAMIC)
767
        gen_op_set_cc_op(s->cc_op);
768
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
769
    gen_movs(s, ot);
770
    gen_op_dec_ECX[s->aflag]();
771
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
772
    s->is_jmp = 3;
773
}
774

    
775
static inline void gen_stos(DisasContext *s, int ot)
776
{
777
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
778
    gen_string_movl_A0_EDI(s);
779
    gen_op_st_T0_A0[ot + s->mem_index]();
780
    gen_op_movl_T0_Dshift[ot]();
781
    if (s->aflag) {
782
        gen_op_addl_EDI_T0();
783
    } else {
784
        gen_op_addw_EDI_T0();
785
    }
786
}
787

    
788
static inline void gen_repz_stos(DisasContext *s, int ot, 
789
                                 unsigned int cur_eip, unsigned int next_eip)
790
{
791
    if (s->cc_op != CC_OP_DYNAMIC)
792
        gen_op_set_cc_op(s->cc_op);
793
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
794
    gen_stos(s, ot);
795
    gen_op_dec_ECX[s->aflag]();
796
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
797
    s->is_jmp = 3;
798
}
799

    
800
static inline void gen_lods(DisasContext *s, int ot)
801
{
802
    gen_string_movl_A0_ESI(s);
803
    gen_op_ld_T0_A0[ot + s->mem_index]();
804
    gen_op_mov_reg_T0[ot][R_EAX]();
805
    gen_op_movl_T0_Dshift[ot]();
806
    if (s->aflag) {
807
        gen_op_addl_ESI_T0();
808
    } else {
809
        gen_op_addw_ESI_T0();
810
    }
811
}
812

    
813
static inline void gen_repz_lods(DisasContext *s, int ot, 
814
                                 unsigned int cur_eip, unsigned int next_eip)
815
{
816
    if (s->cc_op != CC_OP_DYNAMIC)
817
        gen_op_set_cc_op(s->cc_op);
818
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
819
    gen_lods(s, ot);
820
    gen_op_dec_ECX[s->aflag]();
821
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
822
    s->is_jmp = 3;
823
}
824

    
825
static inline void gen_scas(DisasContext *s, int ot)
826
{
827
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
828
    gen_string_movl_A0_EDI(s);
829
    gen_op_ld_T1_A0[ot + s->mem_index]();
830
    gen_op_cmpl_T0_T1_cc();
831
    gen_op_movl_T0_Dshift[ot]();
832
    if (s->aflag) {
833
        gen_op_addl_EDI_T0();
834
    } else {
835
        gen_op_addw_EDI_T0();
836
    }
837
}
838

    
839
#if 0
840
static inline void gen_repz_scas(DisasContext *s, int ot, 
841
                                 unsigned int cur_eip, unsigned int next_eip,
842
                                 int nz)
843
{
844
    if (s->cc_op != CC_OP_DYNAMIC)
845
        gen_op_set_cc_op(s->cc_op);
846
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
847
    gen_scas(s, ot);
848
    gen_op_set_cc_op(CC_OP_SUBB + ot);
849
    gen_op_string_jnz_sub[nz][ot]((long)s->tb, next_eip);
850
    gen_op_dec_ECX[s->aflag]();
851
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
852
    s->is_jmp = 3;
853
}
854
#endif
855

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

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

    
886
static inline void gen_repz_ins(DisasContext *s, int ot, 
887
                                 unsigned int cur_eip, unsigned int next_eip)
888
{
889
    if (s->cc_op != CC_OP_DYNAMIC)
890
        gen_op_set_cc_op(s->cc_op);
891
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
892
    gen_ins(s, ot);
893
    gen_op_dec_ECX[s->aflag]();
894
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
895
    s->is_jmp = 3;
896
}
897

    
898
static inline void gen_outs(DisasContext *s, int ot)
899
{
900
    gen_string_movl_A0_ESI(s);
901
    gen_op_ld_T0_A0[ot + s->mem_index]();
902
    gen_op_out_DX_T0[ot]();
903
    gen_op_movl_T0_Dshift[ot]();
904
    if (s->aflag) {
905
        gen_op_addl_ESI_T0();
906
    } else {
907
        gen_op_addw_ESI_T0();
908
    }
909
}
910

    
911
static inline void gen_repz_outs(DisasContext *s, int ot, 
912
                                 unsigned int cur_eip, unsigned int next_eip)
913
{
914
    if (s->cc_op != CC_OP_DYNAMIC)
915
        gen_op_set_cc_op(s->cc_op);
916
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
917
    gen_outs(s, ot);
918
    gen_op_dec_ECX[s->aflag]();
919
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
920
    s->is_jmp = 3;
921
}
922

    
923
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
924
{
925
    int index, override;
926

    
927
    override = s->override;
928
    if (s->aflag) {
929
        /* 32 bit address */
930
        if (s->addseg && override < 0)
931
            override = R_DS;
932
        if (override >= 0) {
933
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
934
            index = 3 + ot;
935
        } else {
936
            index = ot;
937
        }
938
    } else {
939
        if (override < 0)
940
            override = R_DS;
941
        gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
942
        /* 16 address, always override */
943
        index = 6 + ot;
944
    }
945
    func[index]();
946
}
947

    
948
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
949
{
950
    int index;
951
            
952
    if (s->aflag) {
953
        if (s->addseg) {
954
            index = 3 + ot;
955
        } else {
956
            index = ot;
957
        }
958
    } else {
959
        index = 6 + ot;
960
    }
961
    func[index]();
962
}
963

    
964

    
965
static GenOpFunc *gen_op_in[3] = {
966
    gen_op_inb_T0_T1,
967
    gen_op_inw_T0_T1,
968
    gen_op_inl_T0_T1,
969
};
970

    
971
static GenOpFunc *gen_op_out[3] = {
972
    gen_op_outb_T0_T1,
973
    gen_op_outw_T0_T1,
974
    gen_op_outl_T0_T1,
975
};
976

    
977
enum {
978
    JCC_O,
979
    JCC_B,
980
    JCC_Z,
981
    JCC_BE,
982
    JCC_S,
983
    JCC_P,
984
    JCC_L,
985
    JCC_LE,
986
};
987

    
988
static GenOpFunc3 *gen_jcc_sub[3][8] = {
989
    [OT_BYTE] = {
990
        NULL,
991
        gen_op_jb_subb,
992
        gen_op_jz_subb,
993
        gen_op_jbe_subb,
994
        gen_op_js_subb,
995
        NULL,
996
        gen_op_jl_subb,
997
        gen_op_jle_subb,
998
    },
999
    [OT_WORD] = {
1000
        NULL,
1001
        gen_op_jb_subw,
1002
        gen_op_jz_subw,
1003
        gen_op_jbe_subw,
1004
        gen_op_js_subw,
1005
        NULL,
1006
        gen_op_jl_subw,
1007
        gen_op_jle_subw,
1008
    },
1009
    [OT_LONG] = {
1010
        NULL,
1011
        gen_op_jb_subl,
1012
        gen_op_jz_subl,
1013
        gen_op_jbe_subl,
1014
        gen_op_js_subl,
1015
        NULL,
1016
        gen_op_jl_subl,
1017
        gen_op_jle_subl,
1018
    },
1019
};
1020
static GenOpFunc2 *gen_op_loop[2][4] = {
1021
    [0] = {
1022
        gen_op_loopnzw,
1023
        gen_op_loopzw,
1024
        gen_op_loopw,
1025
        gen_op_jecxzw,
1026
    },
1027
    [1] = {
1028
        gen_op_loopnzl,
1029
        gen_op_loopzl,
1030
        gen_op_loopl,
1031
        gen_op_jecxzl,
1032
    },
1033
};
1034

    
1035
static GenOpFunc *gen_setcc_slow[8] = {
1036
    gen_op_seto_T0_cc,
1037
    gen_op_setb_T0_cc,
1038
    gen_op_setz_T0_cc,
1039
    gen_op_setbe_T0_cc,
1040
    gen_op_sets_T0_cc,
1041
    gen_op_setp_T0_cc,
1042
    gen_op_setl_T0_cc,
1043
    gen_op_setle_T0_cc,
1044
};
1045

    
1046
static GenOpFunc *gen_setcc_sub[3][8] = {
1047
    [OT_BYTE] = {
1048
        NULL,
1049
        gen_op_setb_T0_subb,
1050
        gen_op_setz_T0_subb,
1051
        gen_op_setbe_T0_subb,
1052
        gen_op_sets_T0_subb,
1053
        NULL,
1054
        gen_op_setl_T0_subb,
1055
        gen_op_setle_T0_subb,
1056
    },
1057
    [OT_WORD] = {
1058
        NULL,
1059
        gen_op_setb_T0_subw,
1060
        gen_op_setz_T0_subw,
1061
        gen_op_setbe_T0_subw,
1062
        gen_op_sets_T0_subw,
1063
        NULL,
1064
        gen_op_setl_T0_subw,
1065
        gen_op_setle_T0_subw,
1066
    },
1067
    [OT_LONG] = {
1068
        NULL,
1069
        gen_op_setb_T0_subl,
1070
        gen_op_setz_T0_subl,
1071
        gen_op_setbe_T0_subl,
1072
        gen_op_sets_T0_subl,
1073
        NULL,
1074
        gen_op_setl_T0_subl,
1075
        gen_op_setle_T0_subl,
1076
    },
1077
};
1078

    
1079
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1080
    gen_op_fadd_ST0_FT0,
1081
    gen_op_fmul_ST0_FT0,
1082
    gen_op_fcom_ST0_FT0,
1083
    gen_op_fcom_ST0_FT0,
1084
    gen_op_fsub_ST0_FT0,
1085
    gen_op_fsubr_ST0_FT0,
1086
    gen_op_fdiv_ST0_FT0,
1087
    gen_op_fdivr_ST0_FT0,
1088
};
1089

    
1090
/* NOTE the exception in "r" op ordering */
1091
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1092
    gen_op_fadd_STN_ST0,
1093
    gen_op_fmul_STN_ST0,
1094
    NULL,
1095
    NULL,
1096
    gen_op_fsubr_STN_ST0,
1097
    gen_op_fsub_STN_ST0,
1098
    gen_op_fdivr_STN_ST0,
1099
    gen_op_fdiv_STN_ST0,
1100
};
1101

    
1102
/* if d == OR_TMP0, it means memory operand (address in A0) */
1103
static void gen_op(DisasContext *s1, int op, int ot, int d)
1104
{
1105
    GenOpFunc *gen_update_cc;
1106
    
1107
    if (d != OR_TMP0) {
1108
        gen_op_mov_TN_reg[ot][0][d]();
1109
    } else {
1110
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1111
    }
1112
    switch(op) {
1113
    case OP_ADCL:
1114
    case OP_SBBL:
1115
        if (s1->cc_op != CC_OP_DYNAMIC)
1116
            gen_op_set_cc_op(s1->cc_op);
1117
        if (d != OR_TMP0) {
1118
            gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1119
            gen_op_mov_reg_T0[ot][d]();
1120
        } else {
1121
            gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL]();
1122
        }
1123
        s1->cc_op = CC_OP_DYNAMIC;
1124
        goto the_end;
1125
    case OP_ADDL:
1126
        gen_op_addl_T0_T1();
1127
        s1->cc_op = CC_OP_ADDB + ot;
1128
        gen_update_cc = gen_op_update2_cc;
1129
        break;
1130
    case OP_SUBL:
1131
        gen_op_subl_T0_T1();
1132
        s1->cc_op = CC_OP_SUBB + ot;
1133
        gen_update_cc = gen_op_update2_cc;
1134
        break;
1135
    default:
1136
    case OP_ANDL:
1137
    case OP_ORL:
1138
    case OP_XORL:
1139
        gen_op_arith_T0_T1_cc[op]();
1140
        s1->cc_op = CC_OP_LOGICB + ot;
1141
        gen_update_cc = gen_op_update1_cc;
1142
        break;
1143
    case OP_CMPL:
1144
        gen_op_cmpl_T0_T1_cc();
1145
        s1->cc_op = CC_OP_SUBB + ot;
1146
        gen_update_cc = NULL;
1147
        break;
1148
    }
1149
    if (op != OP_CMPL) {
1150
        if (d != OR_TMP0)
1151
            gen_op_mov_reg_T0[ot][d]();
1152
        else
1153
            gen_op_st_T0_A0[ot + s1->mem_index]();
1154
    }
1155
    /* the flags update must happen after the memory write (precise
1156
       exception support) */
1157
    if (gen_update_cc)
1158
        gen_update_cc();
1159
 the_end: ;
1160
}
1161

    
1162
/* if d == OR_TMP0, it means memory operand (address in A0) */
1163
static void gen_inc(DisasContext *s1, int ot, int d, int c)
1164
{
1165
    if (d != OR_TMP0)
1166
        gen_op_mov_TN_reg[ot][0][d]();
1167
    else
1168
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1169
    if (s1->cc_op != CC_OP_DYNAMIC)
1170
        gen_op_set_cc_op(s1->cc_op);
1171
    if (c > 0) {
1172
        gen_op_incl_T0();
1173
        s1->cc_op = CC_OP_INCB + ot;
1174
    } else {
1175
        gen_op_decl_T0();
1176
        s1->cc_op = CC_OP_DECB + ot;
1177
    }
1178
    if (d != OR_TMP0)
1179
        gen_op_mov_reg_T0[ot][d]();
1180
    else
1181
        gen_op_st_T0_A0[ot + s1->mem_index]();
1182
    gen_op_update_inc_cc();
1183
}
1184

    
1185
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1186
{
1187
    if (d != OR_TMP0)
1188
        gen_op_mov_TN_reg[ot][0][d]();
1189
    else
1190
        gen_op_ld_T0_A0[ot + s1->mem_index]();
1191
    if (s != OR_TMP1)
1192
        gen_op_mov_TN_reg[ot][1][s]();
1193
    /* for zero counts, flags are not updated, so must do it dynamically */
1194
    if (s1->cc_op != CC_OP_DYNAMIC)
1195
        gen_op_set_cc_op(s1->cc_op);
1196
    
1197
    if (d != OR_TMP0)
1198
        gen_op_shift_T0_T1_cc[ot][op]();
1199
    else
1200
        gen_op_shift_mem_T0_T1_cc[ot][op]();
1201
    if (d != OR_TMP0)
1202
        gen_op_mov_reg_T0[ot][d]();
1203
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1204
}
1205

    
1206
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1207
{
1208
    /* currently not optimized */
1209
    gen_op_movl_T1_im(c);
1210
    gen_shift(s1, op, ot, d, OR_TMP1);
1211
}
1212

    
1213
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1214
{
1215
    int havesib;
1216
    int base, disp;
1217
    int index;
1218
    int scale;
1219
    int opreg;
1220
    int mod, rm, code, override, must_add_seg;
1221

    
1222
    override = s->override;
1223
    must_add_seg = s->addseg;
1224
    if (override >= 0)
1225
        must_add_seg = 1;
1226
    mod = (modrm >> 6) & 3;
1227
    rm = modrm & 7;
1228

    
1229
    if (s->aflag) {
1230

    
1231
        havesib = 0;
1232
        base = rm;
1233
        index = 0;
1234
        scale = 0;
1235
        
1236
        if (base == 4) {
1237
            havesib = 1;
1238
            code = ldub(s->pc++);
1239
            scale = (code >> 6) & 3;
1240
            index = (code >> 3) & 7;
1241
            base = code & 7;
1242
        }
1243

    
1244
        switch (mod) {
1245
        case 0:
1246
            if (base == 5) {
1247
                base = -1;
1248
                disp = ldl(s->pc);
1249
                s->pc += 4;
1250
            } else {
1251
                disp = 0;
1252
            }
1253
            break;
1254
        case 1:
1255
            disp = (int8_t)ldub(s->pc++);
1256
            break;
1257
        default:
1258
        case 2:
1259
            disp = ldl(s->pc);
1260
            s->pc += 4;
1261
            break;
1262
        }
1263
        
1264
        if (base >= 0) {
1265
            /* for correct popl handling with esp */
1266
            if (base == 4 && s->popl_esp_hack)
1267
                disp += s->popl_esp_hack;
1268
            gen_op_movl_A0_reg[base]();
1269
            if (disp != 0)
1270
                gen_op_addl_A0_im(disp);
1271
        } else {
1272
            gen_op_movl_A0_im(disp);
1273
        }
1274
        /* XXX: index == 4 is always invalid */
1275
        if (havesib && (index != 4 || scale != 0)) {
1276
            gen_op_addl_A0_reg_sN[scale][index]();
1277
        }
1278
        if (must_add_seg) {
1279
            if (override < 0) {
1280
                if (base == R_EBP || base == R_ESP)
1281
                    override = R_SS;
1282
                else
1283
                    override = R_DS;
1284
            }
1285
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1286
        }
1287
    } else {
1288
        switch (mod) {
1289
        case 0:
1290
            if (rm == 6) {
1291
                disp = lduw(s->pc);
1292
                s->pc += 2;
1293
                gen_op_movl_A0_im(disp);
1294
                rm = 0; /* avoid SS override */
1295
                goto no_rm;
1296
            } else {
1297
                disp = 0;
1298
            }
1299
            break;
1300
        case 1:
1301
            disp = (int8_t)ldub(s->pc++);
1302
            break;
1303
        default:
1304
        case 2:
1305
            disp = lduw(s->pc);
1306
            s->pc += 2;
1307
            break;
1308
        }
1309
        switch(rm) {
1310
        case 0:
1311
            gen_op_movl_A0_reg[R_EBX]();
1312
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1313
            break;
1314
        case 1:
1315
            gen_op_movl_A0_reg[R_EBX]();
1316
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1317
            break;
1318
        case 2:
1319
            gen_op_movl_A0_reg[R_EBP]();
1320
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1321
            break;
1322
        case 3:
1323
            gen_op_movl_A0_reg[R_EBP]();
1324
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1325
            break;
1326
        case 4:
1327
            gen_op_movl_A0_reg[R_ESI]();
1328
            break;
1329
        case 5:
1330
            gen_op_movl_A0_reg[R_EDI]();
1331
            break;
1332
        case 6:
1333
            gen_op_movl_A0_reg[R_EBP]();
1334
            break;
1335
        default:
1336
        case 7:
1337
            gen_op_movl_A0_reg[R_EBX]();
1338
            break;
1339
        }
1340
        if (disp != 0)
1341
            gen_op_addl_A0_im(disp);
1342
        gen_op_andl_A0_ffff();
1343
    no_rm:
1344
        if (must_add_seg) {
1345
            if (override < 0) {
1346
                if (rm == 2 || rm == 3 || rm == 6)
1347
                    override = R_SS;
1348
                else
1349
                    override = R_DS;
1350
            }
1351
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1352
        }
1353
    }
1354

    
1355
    opreg = OR_A0;
1356
    disp = 0;
1357
    *reg_ptr = opreg;
1358
    *offset_ptr = disp;
1359
}
1360

    
1361
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1362
   OR_TMP0 */
1363
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1364
{
1365
    int mod, rm, opreg, disp;
1366

    
1367
    mod = (modrm >> 6) & 3;
1368
    rm = modrm & 7;
1369
    if (mod == 3) {
1370
        if (is_store) {
1371
            if (reg != OR_TMP0)
1372
                gen_op_mov_TN_reg[ot][0][reg]();
1373
            gen_op_mov_reg_T0[ot][rm]();
1374
        } else {
1375
            gen_op_mov_TN_reg[ot][0][rm]();
1376
            if (reg != OR_TMP0)
1377
                gen_op_mov_reg_T0[ot][reg]();
1378
        }
1379
    } else {
1380
        gen_lea_modrm(s, modrm, &opreg, &disp);
1381
        if (is_store) {
1382
            if (reg != OR_TMP0)
1383
                gen_op_mov_TN_reg[ot][0][reg]();
1384
            gen_op_st_T0_A0[ot + s->mem_index]();
1385
        } else {
1386
            gen_op_ld_T0_A0[ot + s->mem_index]();
1387
            if (reg != OR_TMP0)
1388
                gen_op_mov_reg_T0[ot][reg]();
1389
        }
1390
    }
1391
}
1392

    
1393
static inline uint32_t insn_get(DisasContext *s, int ot)
1394
{
1395
    uint32_t ret;
1396

    
1397
    switch(ot) {
1398
    case OT_BYTE:
1399
        ret = ldub(s->pc);
1400
        s->pc++;
1401
        break;
1402
    case OT_WORD:
1403
        ret = lduw(s->pc);
1404
        s->pc += 2;
1405
        break;
1406
    default:
1407
    case OT_LONG:
1408
        ret = ldl(s->pc);
1409
        s->pc += 4;
1410
        break;
1411
    }
1412
    return ret;
1413
}
1414

    
1415
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1416
{
1417
    TranslationBlock *tb;
1418
    int inv, jcc_op;
1419
    GenOpFunc3 *func;
1420

    
1421
    inv = b & 1;
1422
    jcc_op = (b >> 1) & 7;
1423
    switch(s->cc_op) {
1424
        /* we optimize the cmp/jcc case */
1425
    case CC_OP_SUBB:
1426
    case CC_OP_SUBW:
1427
    case CC_OP_SUBL:
1428
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1429
        break;
1430
        
1431
        /* some jumps are easy to compute */
1432
    case CC_OP_ADDB:
1433
    case CC_OP_ADDW:
1434
    case CC_OP_ADDL:
1435
    case CC_OP_ADCB:
1436
    case CC_OP_ADCW:
1437
    case CC_OP_ADCL:
1438
    case CC_OP_SBBB:
1439
    case CC_OP_SBBW:
1440
    case CC_OP_SBBL:
1441
    case CC_OP_LOGICB:
1442
    case CC_OP_LOGICW:
1443
    case CC_OP_LOGICL:
1444
    case CC_OP_INCB:
1445
    case CC_OP_INCW:
1446
    case CC_OP_INCL:
1447
    case CC_OP_DECB:
1448
    case CC_OP_DECW:
1449
    case CC_OP_DECL:
1450
    case CC_OP_SHLB:
1451
    case CC_OP_SHLW:
1452
    case CC_OP_SHLL:
1453
    case CC_OP_SARB:
1454
    case CC_OP_SARW:
1455
    case CC_OP_SARL:
1456
        switch(jcc_op) {
1457
        case JCC_Z:
1458
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1459
            break;
1460
        case JCC_S:
1461
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1462
            break;
1463
        default:
1464
            func = NULL;
1465
            break;
1466
        }
1467
        break;
1468
    default:
1469
        func = NULL;
1470
        break;
1471
    }
1472

    
1473
    if (s->cc_op != CC_OP_DYNAMIC)
1474
        gen_op_set_cc_op(s->cc_op);
1475

    
1476
    if (!func) {
1477
        gen_setcc_slow[jcc_op]();
1478
        func = gen_op_jcc;
1479
    }
1480
    
1481
    tb = s->tb;
1482
    if (!inv) {
1483
        func((long)tb, val, next_eip);
1484
    } else {
1485
        func((long)tb, next_eip, val);
1486
    }
1487
    s->is_jmp = 3;
1488
}
1489

    
1490
static void gen_setcc(DisasContext *s, int b)
1491
{
1492
    int inv, jcc_op;
1493
    GenOpFunc *func;
1494

    
1495
    inv = b & 1;
1496
    jcc_op = (b >> 1) & 7;
1497
    switch(s->cc_op) {
1498
        /* we optimize the cmp/jcc case */
1499
    case CC_OP_SUBB:
1500
    case CC_OP_SUBW:
1501
    case CC_OP_SUBL:
1502
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1503
        if (!func)
1504
            goto slow_jcc;
1505
        break;
1506
        
1507
        /* some jumps are easy to compute */
1508
    case CC_OP_ADDB:
1509
    case CC_OP_ADDW:
1510
    case CC_OP_ADDL:
1511
    case CC_OP_LOGICB:
1512
    case CC_OP_LOGICW:
1513
    case CC_OP_LOGICL:
1514
    case CC_OP_INCB:
1515
    case CC_OP_INCW:
1516
    case CC_OP_INCL:
1517
    case CC_OP_DECB:
1518
    case CC_OP_DECW:
1519
    case CC_OP_DECL:
1520
    case CC_OP_SHLB:
1521
    case CC_OP_SHLW:
1522
    case CC_OP_SHLL:
1523
        switch(jcc_op) {
1524
        case JCC_Z:
1525
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1526
            break;
1527
        case JCC_S:
1528
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1529
            break;
1530
        default:
1531
            goto slow_jcc;
1532
        }
1533
        break;
1534
    default:
1535
    slow_jcc:
1536
        if (s->cc_op != CC_OP_DYNAMIC)
1537
            gen_op_set_cc_op(s->cc_op);
1538
        func = gen_setcc_slow[jcc_op];
1539
        break;
1540
    }
1541
    func();
1542
    if (inv) {
1543
        gen_op_xor_T0_1();
1544
    }
1545
}
1546

    
1547
/* move T0 to seg_reg and compute if the CPU state may change */
1548
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1549
{
1550
    if (s->pe && !s->vm86)
1551
        gen_op_movl_seg_T0(seg_reg, cur_eip);
1552
    else
1553
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1554
    /* abort translation because the register may have a non zero base
1555
       or because ss32 may change */
1556
    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1557
        s->is_jmp = 2; 
1558
}
1559

    
1560
/* generate a push. It depends on ss32, addseg and dflag */
1561
static void gen_push_T0(DisasContext *s)
1562
{
1563
    if (s->ss32) {
1564
        if (!s->addseg) {
1565
            if (s->dflag)
1566
                gen_op_pushl_T0();
1567
            else
1568
                gen_op_pushw_T0();
1569
        } else {
1570
            if (s->dflag)
1571
                gen_op_pushl_ss32_T0();
1572
            else
1573
                gen_op_pushw_ss32_T0();
1574
        }
1575
    } else {
1576
        if (s->dflag)
1577
            gen_op_pushl_ss16_T0();
1578
        else
1579
            gen_op_pushw_ss16_T0();
1580
    }
1581
}
1582

    
1583
/* two step pop is necessary for precise exceptions */
1584
static void gen_pop_T0(DisasContext *s)
1585
{
1586
    if (s->ss32) {
1587
        if (!s->addseg) {
1588
            if (s->dflag)
1589
                gen_op_popl_T0();
1590
            else
1591
                gen_op_popw_T0();
1592
        } else {
1593
            if (s->dflag)
1594
                gen_op_popl_ss32_T0();
1595
            else
1596
                gen_op_popw_ss32_T0();
1597
        }
1598
    } else {
1599
        if (s->dflag)
1600
            gen_op_popl_ss16_T0();
1601
        else
1602
            gen_op_popw_ss16_T0();
1603
    }
1604
}
1605

    
1606
static inline void gen_stack_update(DisasContext *s, int addend)
1607
{
1608
    if (s->ss32) {
1609
        if (addend == 2)
1610
            gen_op_addl_ESP_2();
1611
        else if (addend == 4)
1612
            gen_op_addl_ESP_4();
1613
        else 
1614
            gen_op_addl_ESP_im(addend);
1615
    } else {
1616
        if (addend == 2)
1617
            gen_op_addw_ESP_2();
1618
        else if (addend == 4)
1619
            gen_op_addw_ESP_4();
1620
        else
1621
            gen_op_addw_ESP_im(addend);
1622
    }
1623
}
1624

    
1625
static void gen_pop_update(DisasContext *s)
1626
{
1627
    gen_stack_update(s, 2 << s->dflag);
1628
}
1629

    
1630
static void gen_stack_A0(DisasContext *s)
1631
{
1632
    gen_op_movl_A0_ESP();
1633
    if (!s->ss32)
1634
        gen_op_andl_A0_ffff();
1635
    gen_op_movl_T1_A0();
1636
    if (s->addseg)
1637
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1638
}
1639

    
1640
/* NOTE: wrap around in 16 bit not fully handled */
1641
static void gen_pusha(DisasContext *s)
1642
{
1643
    int i;
1644
    gen_op_movl_A0_ESP();
1645
    gen_op_addl_A0_im(-16 <<  s->dflag);
1646
    if (!s->ss32)
1647
        gen_op_andl_A0_ffff();
1648
    gen_op_movl_T1_A0();
1649
    if (s->addseg)
1650
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1651
    for(i = 0;i < 8; i++) {
1652
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1653
        gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
1654
        gen_op_addl_A0_im(2 <<  s->dflag);
1655
    }
1656
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1657
}
1658

    
1659
/* NOTE: wrap around in 16 bit not fully handled */
1660
static void gen_popa(DisasContext *s)
1661
{
1662
    int i;
1663
    gen_op_movl_A0_ESP();
1664
    if (!s->ss32)
1665
        gen_op_andl_A0_ffff();
1666
    gen_op_movl_T1_A0();
1667
    gen_op_addl_T1_im(16 <<  s->dflag);
1668
    if (s->addseg)
1669
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1670
    for(i = 0;i < 8; i++) {
1671
        /* ESP is not reloaded */
1672
        if (i != 3) {
1673
            gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
1674
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1675
        }
1676
        gen_op_addl_A0_im(2 <<  s->dflag);
1677
    }
1678
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1679
}
1680

    
1681
/* NOTE: wrap around in 16 bit not fully handled */
1682
/* XXX: check this */
1683
static void gen_enter(DisasContext *s, int esp_addend, int level)
1684
{
1685
    int ot, level1, addend, opsize;
1686

    
1687
    ot = s->dflag + OT_WORD;
1688
    level &= 0x1f;
1689
    level1 = level;
1690
    opsize = 2 << s->dflag;
1691

    
1692
    gen_op_movl_A0_ESP();
1693
    gen_op_addl_A0_im(-opsize);
1694
    if (!s->ss32)
1695
        gen_op_andl_A0_ffff();
1696
    gen_op_movl_T1_A0();
1697
    if (s->addseg)
1698
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1699
    /* push bp */
1700
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1701
    gen_op_st_T0_A0[ot + s->mem_index]();
1702
    if (level) {
1703
        while (level--) {
1704
            gen_op_addl_A0_im(-opsize);
1705
            gen_op_addl_T0_im(-opsize);
1706
            gen_op_st_T0_A0[ot + s->mem_index]();
1707
        }
1708
        gen_op_addl_A0_im(-opsize);
1709
        /* XXX: add st_T1_A0 ? */
1710
        gen_op_movl_T0_T1();
1711
        gen_op_st_T0_A0[ot + s->mem_index]();
1712
    }
1713
    gen_op_mov_reg_T1[ot][R_EBP]();
1714
    addend = -esp_addend;
1715
    if (level1)
1716
        addend -= opsize * (level1 + 1);
1717
    gen_op_addl_T1_im(addend);
1718
    gen_op_mov_reg_T1[ot][R_ESP]();
1719
}
1720

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

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

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

    
1751
/* generate a jump to eip. No segment change must happen before as a
1752
   direct call to the next block may occur */
1753
static void gen_jmp(DisasContext *s, unsigned int eip)
1754
{
1755
    TranslationBlock *tb = s->tb;
1756

    
1757
    if (s->cc_op != CC_OP_DYNAMIC)
1758
        gen_op_set_cc_op(s->cc_op);
1759
    gen_op_jmp_tb_next((long)tb, eip);
1760
    s->is_jmp = 3;
1761
}
1762

    
1763
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1764
   is set to true if the instruction sets the PC (last instruction of
1765
   a basic block) */
1766
long disas_insn(DisasContext *s, uint8_t *pc_start)
1767
{
1768
    int b, prefixes, aflag, dflag;
1769
    int shift, ot;
1770
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1771
    unsigned int next_eip;
1772

    
1773
    s->pc = pc_start;
1774
    prefixes = 0;
1775
    aflag = s->code32;
1776
    dflag = s->code32;
1777
    s->override = -1;
1778
 next_byte:
1779
    b = ldub(s->pc);
1780
    s->pc++;
1781
    /* check prefixes */
1782
    switch (b) {
1783
    case 0xf3:
1784
        prefixes |= PREFIX_REPZ;
1785
        goto next_byte;
1786
    case 0xf2:
1787
        prefixes |= PREFIX_REPNZ;
1788
        goto next_byte;
1789
    case 0xf0:
1790
        prefixes |= PREFIX_LOCK;
1791
        goto next_byte;
1792
    case 0x2e:
1793
        s->override = R_CS;
1794
        goto next_byte;
1795
    case 0x36:
1796
        s->override = R_SS;
1797
        goto next_byte;
1798
    case 0x3e:
1799
        s->override = R_DS;
1800
        goto next_byte;
1801
    case 0x26:
1802
        s->override = R_ES;
1803
        goto next_byte;
1804
    case 0x64:
1805
        s->override = R_FS;
1806
        goto next_byte;
1807
    case 0x65:
1808
        s->override = R_GS;
1809
        goto next_byte;
1810
    case 0x66:
1811
        prefixes |= PREFIX_DATA;
1812
        goto next_byte;
1813
    case 0x67:
1814
        prefixes |= PREFIX_ADR;
1815
        goto next_byte;
1816
    }
1817

    
1818
    if (prefixes & PREFIX_DATA)
1819
        dflag ^= 1;
1820
    if (prefixes & PREFIX_ADR)
1821
        aflag ^= 1;
1822

    
1823
    s->prefix = prefixes;
1824
    s->aflag = aflag;
1825
    s->dflag = dflag;
1826

    
1827
    /* lock generation */
1828
    if (prefixes & PREFIX_LOCK)
1829
        gen_op_lock();
1830

    
1831
    /* now check op code */
1832
 reswitch:
1833
    switch(b) {
1834
    case 0x0f:
1835
        /**************************/
1836
        /* extended op code */
1837
        b = ldub(s->pc++) | 0x100;
1838
        goto reswitch;
1839
        
1840
        /**************************/
1841
        /* arith & logic */
1842
    case 0x00 ... 0x05:
1843
    case 0x08 ... 0x0d:
1844
    case 0x10 ... 0x15:
1845
    case 0x18 ... 0x1d:
1846
    case 0x20 ... 0x25:
1847
    case 0x28 ... 0x2d:
1848
    case 0x30 ... 0x35:
1849
    case 0x38 ... 0x3d:
1850
        {
1851
            int op, f, val;
1852
            op = (b >> 3) & 7;
1853
            f = (b >> 1) & 3;
1854

    
1855
            if ((b & 1) == 0)
1856
                ot = OT_BYTE;
1857
            else
1858
                ot = dflag ? OT_LONG : OT_WORD;
1859
            
1860
            switch(f) {
1861
            case 0: /* OP Ev, Gv */
1862
                modrm = ldub(s->pc++);
1863
                reg = ((modrm >> 3) & 7);
1864
                mod = (modrm >> 6) & 3;
1865
                rm = modrm & 7;
1866
                if (mod != 3) {
1867
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1868
                    opreg = OR_TMP0;
1869
                } else if (op == OP_XORL && rm == reg) {
1870
                xor_zero:
1871
                    /* xor reg, reg optimisation */
1872
                    gen_op_movl_T0_0();
1873
                    s->cc_op = CC_OP_LOGICB + ot;
1874
                    gen_op_mov_reg_T0[ot][reg]();
1875
                    gen_op_update1_cc();
1876
                    break;
1877
                } else {
1878
                    opreg = rm;
1879
                }
1880
                gen_op_mov_TN_reg[ot][1][reg]();
1881
                gen_op(s, op, ot, opreg);
1882
                break;
1883
            case 1: /* OP Gv, Ev */
1884
                modrm = ldub(s->pc++);
1885
                mod = (modrm >> 6) & 3;
1886
                reg = ((modrm >> 3) & 7);
1887
                rm = modrm & 7;
1888
                if (mod != 3) {
1889
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1890
                    gen_op_ld_T1_A0[ot + s->mem_index]();
1891
                } else if (op == OP_XORL && rm == reg) {
1892
                    goto xor_zero;
1893
                } else {
1894
                    gen_op_mov_TN_reg[ot][1][rm]();
1895
                }
1896
                gen_op(s, op, ot, reg);
1897
                break;
1898
            case 2: /* OP A, Iv */
1899
                val = insn_get(s, ot);
1900
                gen_op_movl_T1_im(val);
1901
                gen_op(s, op, ot, OR_EAX);
1902
                break;
1903
            }
1904
        }
1905
        break;
1906

    
1907
    case 0x80: /* GRP1 */
1908
    case 0x81:
1909
    case 0x83:
1910
        {
1911
            int val;
1912

    
1913
            if ((b & 1) == 0)
1914
                ot = OT_BYTE;
1915
            else
1916
                ot = dflag ? OT_LONG : OT_WORD;
1917
            
1918
            modrm = ldub(s->pc++);
1919
            mod = (modrm >> 6) & 3;
1920
            rm = modrm & 7;
1921
            op = (modrm >> 3) & 7;
1922
            
1923
            if (mod != 3) {
1924
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1925
                opreg = OR_TMP0;
1926
            } else {
1927
                opreg = rm + OR_EAX;
1928
            }
1929

    
1930
            switch(b) {
1931
            default:
1932
            case 0x80:
1933
            case 0x81:
1934
                val = insn_get(s, ot);
1935
                break;
1936
            case 0x83:
1937
                val = (int8_t)insn_get(s, OT_BYTE);
1938
                break;
1939
            }
1940
            gen_op_movl_T1_im(val);
1941
            gen_op(s, op, ot, opreg);
1942
        }
1943
        break;
1944

    
1945
        /**************************/
1946
        /* inc, dec, and other misc arith */
1947
    case 0x40 ... 0x47: /* inc Gv */
1948
        ot = dflag ? OT_LONG : OT_WORD;
1949
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1950
        break;
1951
    case 0x48 ... 0x4f: /* dec Gv */
1952
        ot = dflag ? OT_LONG : OT_WORD;
1953
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1954
        break;
1955
    case 0xf6: /* GRP3 */
1956
    case 0xf7:
1957
        if ((b & 1) == 0)
1958
            ot = OT_BYTE;
1959
        else
1960
            ot = dflag ? OT_LONG : OT_WORD;
1961

    
1962
        modrm = ldub(s->pc++);
1963
        mod = (modrm >> 6) & 3;
1964
        rm = modrm & 7;
1965
        op = (modrm >> 3) & 7;
1966
        if (mod != 3) {
1967
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1968
            gen_op_ld_T0_A0[ot + s->mem_index]();
1969
        } else {
1970
            gen_op_mov_TN_reg[ot][0][rm]();
1971
        }
1972

    
1973
        switch(op) {
1974
        case 0: /* test */
1975
            val = insn_get(s, ot);
1976
            gen_op_movl_T1_im(val);
1977
            gen_op_testl_T0_T1_cc();
1978
            s->cc_op = CC_OP_LOGICB + ot;
1979
            break;
1980
        case 2: /* not */
1981
            gen_op_notl_T0();
1982
            if (mod != 3) {
1983
                gen_op_st_T0_A0[ot + s->mem_index]();
1984
            } else {
1985
                gen_op_mov_reg_T0[ot][rm]();
1986
            }
1987
            break;
1988
        case 3: /* neg */
1989
            gen_op_negl_T0();
1990
            if (mod != 3) {
1991
                gen_op_st_T0_A0[ot + s->mem_index]();
1992
            } else {
1993
                gen_op_mov_reg_T0[ot][rm]();
1994
            }
1995
            gen_op_update_neg_cc();
1996
            s->cc_op = CC_OP_SUBB + ot;
1997
            break;
1998
        case 4: /* mul */
1999
            switch(ot) {
2000
            case OT_BYTE:
2001
                gen_op_mulb_AL_T0();
2002
                break;
2003
            case OT_WORD:
2004
                gen_op_mulw_AX_T0();
2005
                break;
2006
            default:
2007
            case OT_LONG:
2008
                gen_op_mull_EAX_T0();
2009
                break;
2010
            }
2011
            s->cc_op = CC_OP_MUL;
2012
            break;
2013
        case 5: /* imul */
2014
            switch(ot) {
2015
            case OT_BYTE:
2016
                gen_op_imulb_AL_T0();
2017
                break;
2018
            case OT_WORD:
2019
                gen_op_imulw_AX_T0();
2020
                break;
2021
            default:
2022
            case OT_LONG:
2023
                gen_op_imull_EAX_T0();
2024
                break;
2025
            }
2026
            s->cc_op = CC_OP_MUL;
2027
            break;
2028
        case 6: /* div */
2029
            switch(ot) {
2030
            case OT_BYTE:
2031
                gen_op_divb_AL_T0(pc_start - s->cs_base);
2032
                break;
2033
            case OT_WORD:
2034
                gen_op_divw_AX_T0(pc_start - s->cs_base);
2035
                break;
2036
            default:
2037
            case OT_LONG:
2038
                gen_op_divl_EAX_T0(pc_start - s->cs_base);
2039
                break;
2040
            }
2041
            break;
2042
        case 7: /* idiv */
2043
            switch(ot) {
2044
            case OT_BYTE:
2045
                gen_op_idivb_AL_T0(pc_start - s->cs_base);
2046
                break;
2047
            case OT_WORD:
2048
                gen_op_idivw_AX_T0(pc_start - s->cs_base);
2049
                break;
2050
            default:
2051
            case OT_LONG:
2052
                gen_op_idivl_EAX_T0(pc_start - s->cs_base);
2053
                break;
2054
            }
2055
            break;
2056
        default:
2057
            goto illegal_op;
2058
        }
2059
        break;
2060

    
2061
    case 0xfe: /* GRP4 */
2062
    case 0xff: /* GRP5 */
2063
        if ((b & 1) == 0)
2064
            ot = OT_BYTE;
2065
        else
2066
            ot = dflag ? OT_LONG : OT_WORD;
2067

    
2068
        modrm = ldub(s->pc++);
2069
        mod = (modrm >> 6) & 3;
2070
        rm = modrm & 7;
2071
        op = (modrm >> 3) & 7;
2072
        if (op >= 2 && b == 0xfe) {
2073
            goto illegal_op;
2074
        }
2075
        if (mod != 3) {
2076
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2077
            if (op >= 2 && op != 3 && op != 5)
2078
                gen_op_ld_T0_A0[ot + s->mem_index]();
2079
        } else {
2080
            gen_op_mov_TN_reg[ot][0][rm]();
2081
        }
2082

    
2083
        switch(op) {
2084
        case 0: /* inc Ev */
2085
            if (mod != 3)
2086
                opreg = OR_TMP0;
2087
            else
2088
                opreg = rm;
2089
            gen_inc(s, ot, opreg, 1);
2090
            break;
2091
        case 1: /* dec Ev */
2092
            if (mod != 3)
2093
                opreg = OR_TMP0;
2094
            else
2095
                opreg = rm;
2096
            gen_inc(s, ot, opreg, -1);
2097
            break;
2098
        case 2: /* call Ev */
2099
            /* XXX: optimize if memory (no and is necessary) */
2100
            if (s->dflag == 0)
2101
                gen_op_andl_T0_ffff();
2102
            gen_op_jmp_T0();
2103
            next_eip = s->pc - s->cs_base;
2104
            gen_op_movl_T0_im(next_eip);
2105
            gen_push_T0(s);
2106
            s->is_jmp = 1;
2107
            break;
2108
        case 3: /* lcall Ev */
2109
            gen_op_ld_T1_A0[ot + s->mem_index]();
2110
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2111
            gen_op_ld_T0_A0[OT_WORD + s->mem_index]();
2112
        do_lcall:
2113
            if (s->pe && !s->vm86) {
2114
                if (s->cc_op != CC_OP_DYNAMIC)
2115
                    gen_op_set_cc_op(s->cc_op);
2116
                gen_op_jmp_im(pc_start - s->cs_base);
2117
                gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
2118
            } else {
2119
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2120
            }
2121
            s->is_jmp = 1;
2122
            break;
2123
        case 4: /* jmp Ev */
2124
            if (s->dflag == 0)
2125
                gen_op_andl_T0_ffff();
2126
            gen_op_jmp_T0();
2127
            s->is_jmp = 1;
2128
            break;
2129
        case 5: /* ljmp Ev */
2130
            gen_op_ld_T1_A0[ot + s->mem_index]();
2131
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2132
            gen_op_lduw_T0_A0();
2133
        do_ljmp:
2134
            if (s->pe && !s->vm86) {
2135
                if (s->cc_op != CC_OP_DYNAMIC)
2136
                    gen_op_set_cc_op(s->cc_op);
2137
                gen_op_jmp_im(pc_start - s->cs_base);
2138
                gen_op_ljmp_protected_T0_T1();
2139
            } else {
2140
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
2141
                gen_op_movl_T0_T1();
2142
                gen_op_jmp_T0();
2143
            }
2144
            s->is_jmp = 1;
2145
            break;
2146
        case 6: /* push Ev */
2147
            gen_push_T0(s);
2148
            break;
2149
        default:
2150
            goto illegal_op;
2151
        }
2152
        break;
2153

    
2154
    case 0x84: /* test Ev, Gv */
2155
    case 0x85: 
2156
        if ((b & 1) == 0)
2157
            ot = OT_BYTE;
2158
        else
2159
            ot = dflag ? OT_LONG : OT_WORD;
2160

    
2161
        modrm = ldub(s->pc++);
2162
        mod = (modrm >> 6) & 3;
2163
        rm = modrm & 7;
2164
        reg = (modrm >> 3) & 7;
2165
        
2166
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2167
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
2168
        gen_op_testl_T0_T1_cc();
2169
        s->cc_op = CC_OP_LOGICB + ot;
2170
        break;
2171
        
2172
    case 0xa8: /* test eAX, Iv */
2173
    case 0xa9:
2174
        if ((b & 1) == 0)
2175
            ot = OT_BYTE;
2176
        else
2177
            ot = dflag ? OT_LONG : OT_WORD;
2178
        val = insn_get(s, ot);
2179

    
2180
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
2181
        gen_op_movl_T1_im(val);
2182
        gen_op_testl_T0_T1_cc();
2183
        s->cc_op = CC_OP_LOGICB + ot;
2184
        break;
2185
        
2186
    case 0x98: /* CWDE/CBW */
2187
        if (dflag)
2188
            gen_op_movswl_EAX_AX();
2189
        else
2190
            gen_op_movsbw_AX_AL();
2191
        break;
2192
    case 0x99: /* CDQ/CWD */
2193
        if (dflag)
2194
            gen_op_movslq_EDX_EAX();
2195
        else
2196
            gen_op_movswl_DX_AX();
2197
        break;
2198
    case 0x1af: /* imul Gv, Ev */
2199
    case 0x69: /* imul Gv, Ev, I */
2200
    case 0x6b:
2201
        ot = dflag ? OT_LONG : OT_WORD;
2202
        modrm = ldub(s->pc++);
2203
        reg = ((modrm >> 3) & 7) + OR_EAX;
2204
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2205
        if (b == 0x69) {
2206
            val = insn_get(s, ot);
2207
            gen_op_movl_T1_im(val);
2208
        } else if (b == 0x6b) {
2209
            val = insn_get(s, OT_BYTE);
2210
            gen_op_movl_T1_im(val);
2211
        } else {
2212
            gen_op_mov_TN_reg[ot][1][reg]();
2213
        }
2214

    
2215
        if (ot == OT_LONG) {
2216
            gen_op_imull_T0_T1();
2217
        } else {
2218
            gen_op_imulw_T0_T1();
2219
        }
2220
        gen_op_mov_reg_T0[ot][reg]();
2221
        s->cc_op = CC_OP_MUL;
2222
        break;
2223
    case 0x1c0:
2224
    case 0x1c1: /* xadd Ev, Gv */
2225
        if ((b & 1) == 0)
2226
            ot = OT_BYTE;
2227
        else
2228
            ot = dflag ? OT_LONG : OT_WORD;
2229
        modrm = ldub(s->pc++);
2230
        reg = (modrm >> 3) & 7;
2231
        mod = (modrm >> 6) & 3;
2232
        if (mod == 3) {
2233
            rm = modrm & 7;
2234
            gen_op_mov_TN_reg[ot][0][reg]();
2235
            gen_op_mov_TN_reg[ot][1][rm]();
2236
            gen_op_addl_T0_T1();
2237
            gen_op_mov_reg_T0[ot][rm]();
2238
            gen_op_mov_reg_T1[ot][reg]();
2239
        } else {
2240
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2241
            gen_op_mov_TN_reg[ot][0][reg]();
2242
            gen_op_ld_T1_A0[ot + s->mem_index]();
2243
            gen_op_addl_T0_T1();
2244
            gen_op_st_T0_A0[ot + s->mem_index]();
2245
            gen_op_mov_reg_T1[ot][reg]();
2246
        }
2247
        gen_op_update2_cc();
2248
        s->cc_op = CC_OP_ADDB + ot;
2249
        break;
2250
    case 0x1b0:
2251
    case 0x1b1: /* cmpxchg Ev, Gv */
2252
        if ((b & 1) == 0)
2253
            ot = OT_BYTE;
2254
        else
2255
            ot = dflag ? OT_LONG : OT_WORD;
2256
        modrm = ldub(s->pc++);
2257
        reg = (modrm >> 3) & 7;
2258
        mod = (modrm >> 6) & 3;
2259
        gen_op_mov_TN_reg[ot][1][reg]();
2260
        if (mod == 3) {
2261
            rm = modrm & 7;
2262
            gen_op_mov_TN_reg[ot][0][rm]();
2263
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
2264
            gen_op_mov_reg_T0[ot][rm]();
2265
        } else {
2266
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2267
            gen_op_ld_T0_A0[ot + s->mem_index]();
2268
            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
2269
        }
2270
        s->cc_op = CC_OP_SUBB + ot;
2271
        break;
2272
    case 0x1c7: /* cmpxchg8b */
2273
        modrm = ldub(s->pc++);
2274
        mod = (modrm >> 6) & 3;
2275
        if (mod == 3)
2276
            goto illegal_op;
2277
        if (s->cc_op != CC_OP_DYNAMIC)
2278
            gen_op_set_cc_op(s->cc_op);
2279
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2280
        gen_op_cmpxchg8b();
2281
        s->cc_op = CC_OP_EFLAGS;
2282
        break;
2283
        
2284
        /**************************/
2285
        /* push/pop */
2286
    case 0x50 ... 0x57: /* push */
2287
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2288
        gen_push_T0(s);
2289
        break;
2290
    case 0x58 ... 0x5f: /* pop */
2291
        ot = dflag ? OT_LONG : OT_WORD;
2292
        gen_pop_T0(s);
2293
        gen_op_mov_reg_T0[ot][b & 7]();
2294
        gen_pop_update(s);
2295
        break;
2296
    case 0x60: /* pusha */
2297
        gen_pusha(s);
2298
        break;
2299
    case 0x61: /* popa */
2300
        gen_popa(s);
2301
        break;
2302
    case 0x68: /* push Iv */
2303
    case 0x6a:
2304
        ot = dflag ? OT_LONG : OT_WORD;
2305
        if (b == 0x68)
2306
            val = insn_get(s, ot);
2307
        else
2308
            val = (int8_t)insn_get(s, OT_BYTE);
2309
        gen_op_movl_T0_im(val);
2310
        gen_push_T0(s);
2311
        break;
2312
    case 0x8f: /* pop Ev */
2313
        ot = dflag ? OT_LONG : OT_WORD;
2314
        modrm = ldub(s->pc++);
2315
        gen_pop_T0(s);
2316
        s->popl_esp_hack = 2 << dflag;
2317
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2318
        s->popl_esp_hack = 0;
2319
        gen_pop_update(s);
2320
        break;
2321
    case 0xc8: /* enter */
2322
        {
2323
            int level;
2324
            val = lduw(s->pc);
2325
            s->pc += 2;
2326
            level = ldub(s->pc++);
2327
            gen_enter(s, val, level);
2328
        }
2329
        break;
2330
    case 0xc9: /* leave */
2331
        /* XXX: exception not precise (ESP is updated before potential exception) */
2332
        if (s->ss32) {
2333
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2334
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2335
        } else {
2336
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2337
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2338
        }
2339
        gen_pop_T0(s);
2340
        ot = dflag ? OT_LONG : OT_WORD;
2341
        gen_op_mov_reg_T0[ot][R_EBP]();
2342
        gen_pop_update(s);
2343
        break;
2344
    case 0x06: /* push es */
2345
    case 0x0e: /* push cs */
2346
    case 0x16: /* push ss */
2347
    case 0x1e: /* push ds */
2348
        gen_op_movl_T0_seg(b >> 3);
2349
        gen_push_T0(s);
2350
        break;
2351
    case 0x1a0: /* push fs */
2352
    case 0x1a8: /* push gs */
2353
        gen_op_movl_T0_seg((b >> 3) & 7);
2354
        gen_push_T0(s);
2355
        break;
2356
    case 0x07: /* pop es */
2357
    case 0x17: /* pop ss */
2358
    case 0x1f: /* pop ds */
2359
        gen_pop_T0(s);
2360
        gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
2361
        gen_pop_update(s);
2362
        /* XXX: if reg == SS, inhibit interrupts/trace */
2363
        break;
2364
    case 0x1a1: /* pop fs */
2365
    case 0x1a9: /* pop gs */
2366
        gen_pop_T0(s);
2367
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2368
        gen_pop_update(s);
2369
        break;
2370

    
2371
        /**************************/
2372
        /* mov */
2373
    case 0x88:
2374
    case 0x89: /* mov Gv, Ev */
2375
        if ((b & 1) == 0)
2376
            ot = OT_BYTE;
2377
        else
2378
            ot = dflag ? OT_LONG : OT_WORD;
2379
        modrm = ldub(s->pc++);
2380
        reg = (modrm >> 3) & 7;
2381
        
2382
        /* generate a generic store */
2383
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2384
        break;
2385
    case 0xc6:
2386
    case 0xc7: /* mov Ev, Iv */
2387
        if ((b & 1) == 0)
2388
            ot = OT_BYTE;
2389
        else
2390
            ot = dflag ? OT_LONG : OT_WORD;
2391
        modrm = ldub(s->pc++);
2392
        mod = (modrm >> 6) & 3;
2393
        if (mod != 3)
2394
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2395
        val = insn_get(s, ot);
2396
        gen_op_movl_T0_im(val);
2397
        if (mod != 3)
2398
            gen_op_st_T0_A0[ot + s->mem_index]();
2399
        else
2400
            gen_op_mov_reg_T0[ot][modrm & 7]();
2401
        break;
2402
    case 0x8a:
2403
    case 0x8b: /* mov Ev, Gv */
2404
        if ((b & 1) == 0)
2405
            ot = OT_BYTE;
2406
        else
2407
            ot = dflag ? OT_LONG : OT_WORD;
2408
        modrm = ldub(s->pc++);
2409
        reg = (modrm >> 3) & 7;
2410
        
2411
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2412
        gen_op_mov_reg_T0[ot][reg]();
2413
        break;
2414
    case 0x8e: /* mov seg, Gv */
2415
        modrm = ldub(s->pc++);
2416
        reg = (modrm >> 3) & 7;
2417
        if (reg >= 6 || reg == R_CS)
2418
            goto illegal_op;
2419
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2420
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2421
        /* XXX: if reg == SS, inhibit interrupts/trace */
2422
        break;
2423
    case 0x8c: /* mov Gv, seg */
2424
        modrm = ldub(s->pc++);
2425
        reg = (modrm >> 3) & 7;
2426
        mod = (modrm >> 6) & 3;
2427
        if (reg >= 6)
2428
            goto illegal_op;
2429
        gen_op_movl_T0_seg(reg);
2430
        ot = OT_WORD;
2431
        if (mod == 3 && dflag)
2432
            ot = OT_LONG;
2433
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2434
        break;
2435

    
2436
    case 0x1b6: /* movzbS Gv, Eb */
2437
    case 0x1b7: /* movzwS Gv, Eb */
2438
    case 0x1be: /* movsbS Gv, Eb */
2439
    case 0x1bf: /* movswS Gv, Eb */
2440
        {
2441
            int d_ot;
2442
            /* d_ot is the size of destination */
2443
            d_ot = dflag + OT_WORD;
2444
            /* ot is the size of source */
2445
            ot = (b & 1) + OT_BYTE;
2446
            modrm = ldub(s->pc++);
2447
            reg = ((modrm >> 3) & 7) + OR_EAX;
2448
            mod = (modrm >> 6) & 3;
2449
            rm = modrm & 7;
2450
            
2451
            if (mod == 3) {
2452
                gen_op_mov_TN_reg[ot][0][rm]();
2453
                switch(ot | (b & 8)) {
2454
                case OT_BYTE:
2455
                    gen_op_movzbl_T0_T0();
2456
                    break;
2457
                case OT_BYTE | 8:
2458
                    gen_op_movsbl_T0_T0();
2459
                    break;
2460
                case OT_WORD:
2461
                    gen_op_movzwl_T0_T0();
2462
                    break;
2463
                default:
2464
                case OT_WORD | 8:
2465
                    gen_op_movswl_T0_T0();
2466
                    break;
2467
                }
2468
                gen_op_mov_reg_T0[d_ot][reg]();
2469
            } else {
2470
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2471
                if (b & 8) {
2472
                    gen_op_lds_T0_A0[ot + s->mem_index]();
2473
                } else {
2474
                    gen_op_ldu_T0_A0[ot + s->mem_index]();
2475
                }
2476
                gen_op_mov_reg_T0[d_ot][reg]();
2477
            }
2478
        }
2479
        break;
2480

    
2481
    case 0x8d: /* lea */
2482
        ot = dflag ? OT_LONG : OT_WORD;
2483
        modrm = ldub(s->pc++);
2484
        reg = (modrm >> 3) & 7;
2485
        /* we must ensure that no segment is added */
2486
        s->override = -1;
2487
        val = s->addseg;
2488
        s->addseg = 0;
2489
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2490
        s->addseg = val;
2491
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2492
        break;
2493
        
2494
    case 0xa0: /* mov EAX, Ov */
2495
    case 0xa1:
2496
    case 0xa2: /* mov Ov, EAX */
2497
    case 0xa3:
2498
        if ((b & 1) == 0)
2499
            ot = OT_BYTE;
2500
        else
2501
            ot = dflag ? OT_LONG : OT_WORD;
2502
        if (s->aflag)
2503
            offset_addr = insn_get(s, OT_LONG);
2504
        else
2505
            offset_addr = insn_get(s, OT_WORD);
2506
        gen_op_movl_A0_im(offset_addr);
2507
        /* handle override */
2508
        {
2509
            int override, must_add_seg;
2510
            must_add_seg = s->addseg;
2511
            if (s->override >= 0) {
2512
                override = s->override;
2513
                must_add_seg = 1;
2514
            } else {
2515
                override = R_DS;
2516
            }
2517
            if (must_add_seg) {
2518
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2519
            }
2520
        }
2521
        if ((b & 2) == 0) {
2522
            gen_op_ld_T0_A0[ot + s->mem_index]();
2523
            gen_op_mov_reg_T0[ot][R_EAX]();
2524
        } else {
2525
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2526
            gen_op_st_T0_A0[ot + s->mem_index]();
2527
        }
2528
        break;
2529
    case 0xd7: /* xlat */
2530
        gen_op_movl_A0_reg[R_EBX]();
2531
        gen_op_addl_A0_AL();
2532
        if (s->aflag == 0)
2533
            gen_op_andl_A0_ffff();
2534
        /* handle override */
2535
        {
2536
            int override, must_add_seg;
2537
            must_add_seg = s->addseg;
2538
            override = R_DS;
2539
            if (s->override >= 0) {
2540
                override = s->override;
2541
                must_add_seg = 1;
2542
            } else {
2543
                override = R_DS;
2544
            }
2545
            if (must_add_seg) {
2546
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2547
            }
2548
        }
2549
        gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
2550
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2551
        break;
2552
    case 0xb0 ... 0xb7: /* mov R, Ib */
2553
        val = insn_get(s, OT_BYTE);
2554
        gen_op_movl_T0_im(val);
2555
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2556
        break;
2557
    case 0xb8 ... 0xbf: /* mov R, Iv */
2558
        ot = dflag ? OT_LONG : OT_WORD;
2559
        val = insn_get(s, ot);
2560
        reg = OR_EAX + (b & 7);
2561
        gen_op_movl_T0_im(val);
2562
        gen_op_mov_reg_T0[ot][reg]();
2563
        break;
2564

    
2565
    case 0x91 ... 0x97: /* xchg R, EAX */
2566
        ot = dflag ? OT_LONG : OT_WORD;
2567
        reg = b & 7;
2568
        rm = R_EAX;
2569
        goto do_xchg_reg;
2570
    case 0x86:
2571
    case 0x87: /* xchg Ev, Gv */
2572
        if ((b & 1) == 0)
2573
            ot = OT_BYTE;
2574
        else
2575
            ot = dflag ? OT_LONG : OT_WORD;
2576
        modrm = ldub(s->pc++);
2577
        reg = (modrm >> 3) & 7;
2578
        mod = (modrm >> 6) & 3;
2579
        if (mod == 3) {
2580
            rm = modrm & 7;
2581
        do_xchg_reg:
2582
            gen_op_mov_TN_reg[ot][0][reg]();
2583
            gen_op_mov_TN_reg[ot][1][rm]();
2584
            gen_op_mov_reg_T0[ot][rm]();
2585
            gen_op_mov_reg_T1[ot][reg]();
2586
        } else {
2587
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2588
            gen_op_mov_TN_reg[ot][0][reg]();
2589
            /* for xchg, lock is implicit */
2590
            if (!(prefixes & PREFIX_LOCK))
2591
                gen_op_lock();
2592
            gen_op_ld_T1_A0[ot + s->mem_index]();
2593
            gen_op_st_T0_A0[ot + s->mem_index]();
2594
            if (!(prefixes & PREFIX_LOCK))
2595
                gen_op_unlock();
2596
            gen_op_mov_reg_T1[ot][reg]();
2597
        }
2598
        break;
2599
    case 0xc4: /* les Gv */
2600
        op = R_ES;
2601
        goto do_lxx;
2602
    case 0xc5: /* lds Gv */
2603
        op = R_DS;
2604
        goto do_lxx;
2605
    case 0x1b2: /* lss Gv */
2606
        op = R_SS;
2607
        goto do_lxx;
2608
    case 0x1b4: /* lfs Gv */
2609
        op = R_FS;
2610
        goto do_lxx;
2611
    case 0x1b5: /* lgs Gv */
2612
        op = R_GS;
2613
    do_lxx:
2614
        ot = dflag ? OT_LONG : OT_WORD;
2615
        modrm = ldub(s->pc++);
2616
        reg = (modrm >> 3) & 7;
2617
        mod = (modrm >> 6) & 3;
2618
        if (mod == 3)
2619
            goto illegal_op;
2620
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2621
        gen_op_ld_T1_A0[ot + s->mem_index]();
2622
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2623
        /* load the segment first to handle exceptions properly */
2624
        gen_op_lduw_T0_A0();
2625
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2626
        /* then put the data */
2627
        gen_op_mov_reg_T1[ot][reg]();
2628
        break;
2629
        
2630
        /************************/
2631
        /* shifts */
2632
    case 0xc0:
2633
    case 0xc1:
2634
        /* shift Ev,Ib */
2635
        shift = 2;
2636
    grp2:
2637
        {
2638
            if ((b & 1) == 0)
2639
                ot = OT_BYTE;
2640
            else
2641
                ot = dflag ? OT_LONG : OT_WORD;
2642
            
2643
            modrm = ldub(s->pc++);
2644
            mod = (modrm >> 6) & 3;
2645
            rm = modrm & 7;
2646
            op = (modrm >> 3) & 7;
2647
            
2648
            if (mod != 3) {
2649
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2650
                opreg = OR_TMP0;
2651
            } else {
2652
                opreg = rm + OR_EAX;
2653
            }
2654

    
2655
            /* simpler op */
2656
            if (shift == 0) {
2657
                gen_shift(s, op, ot, opreg, OR_ECX);
2658
            } else {
2659
                if (shift == 2) {
2660
                    shift = ldub(s->pc++);
2661
                }
2662
                gen_shifti(s, op, ot, opreg, shift);
2663
            }
2664
        }
2665
        break;
2666
    case 0xd0:
2667
    case 0xd1:
2668
        /* shift Ev,1 */
2669
        shift = 1;
2670
        goto grp2;
2671
    case 0xd2:
2672
    case 0xd3:
2673
        /* shift Ev,cl */
2674
        shift = 0;
2675
        goto grp2;
2676

    
2677
    case 0x1a4: /* shld imm */
2678
        op = 0;
2679
        shift = 1;
2680
        goto do_shiftd;
2681
    case 0x1a5: /* shld cl */
2682
        op = 0;
2683
        shift = 0;
2684
        goto do_shiftd;
2685
    case 0x1ac: /* shrd imm */
2686
        op = 1;
2687
        shift = 1;
2688
        goto do_shiftd;
2689
    case 0x1ad: /* shrd cl */
2690
        op = 1;
2691
        shift = 0;
2692
    do_shiftd:
2693
        ot = dflag ? OT_LONG : OT_WORD;
2694
        modrm = ldub(s->pc++);
2695
        mod = (modrm >> 6) & 3;
2696
        rm = modrm & 7;
2697
        reg = (modrm >> 3) & 7;
2698
        
2699
        if (mod != 3) {
2700
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2701
            gen_op_ld_T0_A0[ot + s->mem_index]();
2702
        } else {
2703
            gen_op_mov_TN_reg[ot][0][rm]();
2704
        }
2705
        gen_op_mov_TN_reg[ot][1][reg]();
2706
        
2707
        if (shift) {
2708
            val = ldub(s->pc++);
2709
            val &= 0x1f;
2710
            if (val) {
2711
                if (mod == 3)
2712
                    gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2713
                else
2714
                    gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
2715
                if (op == 0 && ot != OT_WORD)
2716
                    s->cc_op = CC_OP_SHLB + ot;
2717
                else
2718
                    s->cc_op = CC_OP_SARB + ot;
2719
            }
2720
        } else {
2721
            if (s->cc_op != CC_OP_DYNAMIC)
2722
                gen_op_set_cc_op(s->cc_op);
2723
            if (mod == 3)
2724
                gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2725
            else
2726
                gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
2727
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2728
        }
2729
        if (mod == 3) {
2730
            gen_op_mov_reg_T0[ot][rm]();
2731
        }
2732
        break;
2733

    
2734
        /************************/
2735
        /* floats */
2736
    case 0xd8 ... 0xdf: 
2737
        modrm = ldub(s->pc++);
2738
        mod = (modrm >> 6) & 3;
2739
        rm = modrm & 7;
2740
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2741
        
2742
        if (mod != 3) {
2743
            /* memory op */
2744
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2745
            switch(op) {
2746
            case 0x00 ... 0x07: /* fxxxs */
2747
            case 0x10 ... 0x17: /* fixxxl */
2748
            case 0x20 ... 0x27: /* fxxxl */
2749
            case 0x30 ... 0x37: /* fixxx */
2750
                {
2751
                    int op1;
2752
                    op1 = op & 7;
2753

    
2754
                    switch(op >> 4) {
2755
                    case 0:
2756
                        gen_op_flds_FT0_A0();
2757
                        break;
2758
                    case 1:
2759
                        gen_op_fildl_FT0_A0();
2760
                        break;
2761
                    case 2:
2762
                        gen_op_fldl_FT0_A0();
2763
                        break;
2764
                    case 3:
2765
                    default:
2766
                        gen_op_fild_FT0_A0();
2767
                        break;
2768
                    }
2769
                    
2770
                    gen_op_fp_arith_ST0_FT0[op1]();
2771
                    if (op1 == 3) {
2772
                        /* fcomp needs pop */
2773
                        gen_op_fpop();
2774
                    }
2775
                }
2776
                break;
2777
            case 0x08: /* flds */
2778
            case 0x0a: /* fsts */
2779
            case 0x0b: /* fstps */
2780
            case 0x18: /* fildl */
2781
            case 0x1a: /* fistl */
2782
            case 0x1b: /* fistpl */
2783
            case 0x28: /* fldl */
2784
            case 0x2a: /* fstl */
2785
            case 0x2b: /* fstpl */
2786
            case 0x38: /* filds */
2787
            case 0x3a: /* fists */
2788
            case 0x3b: /* fistps */
2789
                
2790
                switch(op & 7) {
2791
                case 0:
2792
                    switch(op >> 4) {
2793
                    case 0:
2794
                        gen_op_flds_ST0_A0();
2795
                        break;
2796
                    case 1:
2797
                        gen_op_fildl_ST0_A0();
2798
                        break;
2799
                    case 2:
2800
                        gen_op_fldl_ST0_A0();
2801
                        break;
2802
                    case 3:
2803
                    default:
2804
                        gen_op_fild_ST0_A0();
2805
                        break;
2806
                    }
2807
                    break;
2808
                default:
2809
                    switch(op >> 4) {
2810
                    case 0:
2811
                        gen_op_fsts_ST0_A0();
2812
                        break;
2813
                    case 1:
2814
                        gen_op_fistl_ST0_A0();
2815
                        break;
2816
                    case 2:
2817
                        gen_op_fstl_ST0_A0();
2818
                        break;
2819
                    case 3:
2820
                    default:
2821
                        gen_op_fist_ST0_A0();
2822
                        break;
2823
                    }
2824
                    if ((op & 7) == 3)
2825
                        gen_op_fpop();
2826
                    break;
2827
                }
2828
                break;
2829
            case 0x0c: /* fldenv mem */
2830
                gen_op_fldenv_A0(s->dflag);
2831
                break;
2832
            case 0x0d: /* fldcw mem */
2833
                gen_op_fldcw_A0();
2834
                break;
2835
            case 0x0e: /* fnstenv mem */
2836
                gen_op_fnstenv_A0(s->dflag);
2837
                break;
2838
            case 0x0f: /* fnstcw mem */
2839
                gen_op_fnstcw_A0();
2840
                break;
2841
            case 0x1d: /* fldt mem */
2842
                gen_op_fldt_ST0_A0();
2843
                break;
2844
            case 0x1f: /* fstpt mem */
2845
                gen_op_fstt_ST0_A0();
2846
                gen_op_fpop();
2847
                break;
2848
            case 0x2c: /* frstor mem */
2849
                gen_op_frstor_A0(s->dflag);
2850
                break;
2851
            case 0x2e: /* fnsave mem */
2852
                gen_op_fnsave_A0(s->dflag);
2853
                break;
2854
            case 0x2f: /* fnstsw mem */
2855
                gen_op_fnstsw_A0();
2856
                break;
2857
            case 0x3c: /* fbld */
2858
                gen_op_fbld_ST0_A0();
2859
                break;
2860
            case 0x3e: /* fbstp */
2861
                gen_op_fbst_ST0_A0();
2862
                gen_op_fpop();
2863
                break;
2864
            case 0x3d: /* fildll */
2865
                gen_op_fildll_ST0_A0();
2866
                break;
2867
            case 0x3f: /* fistpll */
2868
                gen_op_fistll_ST0_A0();
2869
                gen_op_fpop();
2870
                break;
2871
            default:
2872
                goto illegal_op;
2873
            }
2874
        } else {
2875
            /* register float ops */
2876
            opreg = rm;
2877

    
2878
            switch(op) {
2879
            case 0x08: /* fld sti */
2880
                gen_op_fpush();
2881
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2882
                break;
2883
            case 0x09: /* fxchg sti */
2884
                gen_op_fxchg_ST0_STN(opreg);
2885
                break;
2886
            case 0x0a: /* grp d9/2 */
2887
                switch(rm) {
2888
                case 0: /* fnop */
2889
                    break;
2890
                default:
2891
                    goto illegal_op;
2892
                }
2893
                break;
2894
            case 0x0c: /* grp d9/4 */
2895
                switch(rm) {
2896
                case 0: /* fchs */
2897
                    gen_op_fchs_ST0();
2898
                    break;
2899
                case 1: /* fabs */
2900
                    gen_op_fabs_ST0();
2901
                    break;
2902
                case 4: /* ftst */
2903
                    gen_op_fldz_FT0();
2904
                    gen_op_fcom_ST0_FT0();
2905
                    break;
2906
                case 5: /* fxam */
2907
                    gen_op_fxam_ST0();
2908
                    break;
2909
                default:
2910
                    goto illegal_op;
2911
                }
2912
                break;
2913
            case 0x0d: /* grp d9/5 */
2914
                {
2915
                    switch(rm) {
2916
                    case 0:
2917
                        gen_op_fpush();
2918
                        gen_op_fld1_ST0();
2919
                        break;
2920
                    case 1:
2921
                        gen_op_fpush();
2922
                        gen_op_fldl2t_ST0();
2923
                        break;
2924
                    case 2:
2925
                        gen_op_fpush();
2926
                        gen_op_fldl2e_ST0();
2927
                        break;
2928
                    case 3:
2929
                        gen_op_fpush();
2930
                        gen_op_fldpi_ST0();
2931
                        break;
2932
                    case 4:
2933
                        gen_op_fpush();
2934
                        gen_op_fldlg2_ST0();
2935
                        break;
2936
                    case 5:
2937
                        gen_op_fpush();
2938
                        gen_op_fldln2_ST0();
2939
                        break;
2940
                    case 6:
2941
                        gen_op_fpush();
2942
                        gen_op_fldz_ST0();
2943
                        break;
2944
                    default:
2945
                        goto illegal_op;
2946
                    }
2947
                }
2948
                break;
2949
            case 0x0e: /* grp d9/6 */
2950
                switch(rm) {
2951
                case 0: /* f2xm1 */
2952
                    gen_op_f2xm1();
2953
                    break;
2954
                case 1: /* fyl2x */
2955
                    gen_op_fyl2x();
2956
                    break;
2957
                case 2: /* fptan */
2958
                    gen_op_fptan();
2959
                    break;
2960
                case 3: /* fpatan */
2961
                    gen_op_fpatan();
2962
                    break;
2963
                case 4: /* fxtract */
2964
                    gen_op_fxtract();
2965
                    break;
2966
                case 5: /* fprem1 */
2967
                    gen_op_fprem1();
2968
                    break;
2969
                case 6: /* fdecstp */
2970
                    gen_op_fdecstp();
2971
                    break;
2972
                default:
2973
                case 7: /* fincstp */
2974
                    gen_op_fincstp();
2975
                    break;
2976
                }
2977
                break;
2978
            case 0x0f: /* grp d9/7 */
2979
                switch(rm) {
2980
                case 0: /* fprem */
2981
                    gen_op_fprem();
2982
                    break;
2983
                case 1: /* fyl2xp1 */
2984
                    gen_op_fyl2xp1();
2985
                    break;
2986
                case 2: /* fsqrt */
2987
                    gen_op_fsqrt();
2988
                    break;
2989
                case 3: /* fsincos */
2990
                    gen_op_fsincos();
2991
                    break;
2992
                case 5: /* fscale */
2993
                    gen_op_fscale();
2994
                    break;
2995
                case 4: /* frndint */
2996
                    gen_op_frndint();
2997
                    break;
2998
                case 6: /* fsin */
2999
                    gen_op_fsin();
3000
                    break;
3001
                default:
3002
                case 7: /* fcos */
3003
                    gen_op_fcos();
3004
                    break;
3005
                }
3006
                break;
3007
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
3008
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
3009
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
3010
                {
3011
                    int op1;
3012
                    
3013
                    op1 = op & 7;
3014
                    if (op >= 0x20) {
3015
                        gen_op_fp_arith_STN_ST0[op1](opreg);
3016
                        if (op >= 0x30)
3017
                            gen_op_fpop();
3018
                    } else {
3019
                        gen_op_fmov_FT0_STN(opreg);
3020
                        gen_op_fp_arith_ST0_FT0[op1]();
3021
                    }
3022
                }
3023
                break;
3024
            case 0x02: /* fcom */
3025
                gen_op_fmov_FT0_STN(opreg);
3026
                gen_op_fcom_ST0_FT0();
3027
                break;
3028
            case 0x03: /* fcomp */
3029
                gen_op_fmov_FT0_STN(opreg);
3030
                gen_op_fcom_ST0_FT0();
3031
                gen_op_fpop();
3032
                break;
3033
            case 0x15: /* da/5 */
3034
                switch(rm) {
3035
                case 1: /* fucompp */
3036
                    gen_op_fmov_FT0_STN(1);
3037
                    gen_op_fucom_ST0_FT0();
3038
                    gen_op_fpop();
3039
                    gen_op_fpop();
3040
                    break;
3041
                default:
3042
                    goto illegal_op;
3043
                }
3044
                break;
3045
            case 0x1c:
3046
                switch(rm) {
3047
                case 0: /* feni (287 only, just do nop here) */
3048
                    break;
3049
                case 1: /* fdisi (287 only, just do nop here) */
3050
                    break;
3051
                case 2: /* fclex */
3052
                    gen_op_fclex();
3053
                    break;
3054
                case 3: /* fninit */
3055
                    gen_op_fninit();
3056
                    break;
3057
                case 4: /* fsetpm (287 only, just do nop here) */
3058
                    break;
3059
                default:
3060
                    goto illegal_op;
3061
                }
3062
                break;
3063
            case 0x1d: /* fucomi */
3064
                if (s->cc_op != CC_OP_DYNAMIC)
3065
                    gen_op_set_cc_op(s->cc_op);
3066
                gen_op_fmov_FT0_STN(opreg);
3067
                gen_op_fucomi_ST0_FT0();
3068
                s->cc_op = CC_OP_EFLAGS;
3069
                break;
3070
            case 0x1e: /* fcomi */
3071
                if (s->cc_op != CC_OP_DYNAMIC)
3072
                    gen_op_set_cc_op(s->cc_op);
3073
                gen_op_fmov_FT0_STN(opreg);
3074
                gen_op_fcomi_ST0_FT0();
3075
                s->cc_op = CC_OP_EFLAGS;
3076
                break;
3077
            case 0x2a: /* fst sti */
3078
                gen_op_fmov_STN_ST0(opreg);
3079
                break;
3080
            case 0x2b: /* fstp sti */
3081
                gen_op_fmov_STN_ST0(opreg);
3082
                gen_op_fpop();
3083
                break;
3084
            case 0x2c: /* fucom st(i) */
3085
                gen_op_fmov_FT0_STN(opreg);
3086
                gen_op_fucom_ST0_FT0();
3087
                break;
3088
            case 0x2d: /* fucomp st(i) */
3089
                gen_op_fmov_FT0_STN(opreg);
3090
                gen_op_fucom_ST0_FT0();
3091
                gen_op_fpop();
3092
                break;
3093
            case 0x33: /* de/3 */
3094
                switch(rm) {
3095
                case 1: /* fcompp */
3096
                    gen_op_fmov_FT0_STN(1);
3097
                    gen_op_fcom_ST0_FT0();
3098
                    gen_op_fpop();
3099
                    gen_op_fpop();
3100
                    break;
3101
                default:
3102
                    goto illegal_op;
3103
                }
3104
                break;
3105
            case 0x3c: /* df/4 */
3106
                switch(rm) {
3107
                case 0:
3108
                    gen_op_fnstsw_EAX();
3109
                    break;
3110
                default:
3111
                    goto illegal_op;
3112
                }
3113
                break;
3114
            case 0x3d: /* fucomip */
3115
                if (s->cc_op != CC_OP_DYNAMIC)
3116
                    gen_op_set_cc_op(s->cc_op);
3117
                gen_op_fmov_FT0_STN(opreg);
3118
                gen_op_fucomi_ST0_FT0();
3119
                gen_op_fpop();
3120
                s->cc_op = CC_OP_EFLAGS;
3121
                break;
3122
            case 0x3e: /* fcomip */
3123
                if (s->cc_op != CC_OP_DYNAMIC)
3124
                    gen_op_set_cc_op(s->cc_op);
3125
                gen_op_fmov_FT0_STN(opreg);
3126
                gen_op_fcomi_ST0_FT0();
3127
                gen_op_fpop();
3128
                s->cc_op = CC_OP_EFLAGS;
3129
                break;
3130
            default:
3131
                goto illegal_op;
3132
            }
3133
        }
3134
        break;
3135
        /************************/
3136
        /* string ops */
3137

    
3138
    case 0xa4: /* movsS */
3139
    case 0xa5:
3140
        if ((b & 1) == 0)
3141
            ot = OT_BYTE;
3142
        else
3143
            ot = dflag ? OT_LONG : OT_WORD;
3144

    
3145
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3146
            gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3147
        } else {
3148
            gen_movs(s, ot);
3149
        }
3150
        break;
3151
        
3152
    case 0xaa: /* stosS */
3153
    case 0xab:
3154
        if ((b & 1) == 0)
3155
            ot = OT_BYTE;
3156
        else
3157
            ot = dflag ? OT_LONG : OT_WORD;
3158

    
3159
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3160
            gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3161
        } else {
3162
            gen_stos(s, ot);
3163
        }
3164
        break;
3165
    case 0xac: /* lodsS */
3166
    case 0xad:
3167
        if ((b & 1) == 0)
3168
            ot = OT_BYTE;
3169
        else
3170
            ot = dflag ? OT_LONG : OT_WORD;
3171
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3172
            gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3173
        } else {
3174
            gen_lods(s, ot);
3175
        }
3176
        break;
3177
    case 0xae: /* scasS */
3178
    case 0xaf:
3179
        if ((b & 1) == 0)
3180
            ot = OT_BYTE;
3181
        else
3182
                ot = dflag ? OT_LONG : OT_WORD;
3183
        if (prefixes & PREFIX_REPNZ) {
3184
            if (s->cc_op != CC_OP_DYNAMIC)
3185
                gen_op_set_cc_op(s->cc_op);
3186
            gen_string_es(s, ot, gen_op_scas + STRINGOP_NB);
3187
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
3188
        } else if (prefixes & PREFIX_REPZ) {
3189
            if (s->cc_op != CC_OP_DYNAMIC)
3190
                gen_op_set_cc_op(s->cc_op);
3191
            gen_string_es(s, ot, gen_op_scas);
3192
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
3193
        } else {
3194
            gen_scas(s, ot);
3195
            s->cc_op = CC_OP_SUBB + ot;
3196
        }
3197
        break;
3198

    
3199
    case 0xa6: /* cmpsS */
3200
    case 0xa7:
3201
        if ((b & 1) == 0)
3202
            ot = OT_BYTE;
3203
        else
3204
            ot = dflag ? OT_LONG : OT_WORD;
3205
        if (prefixes & PREFIX_REPNZ) {
3206
            if (s->cc_op != CC_OP_DYNAMIC)
3207
                gen_op_set_cc_op(s->cc_op);
3208
            gen_string_ds(s, ot, gen_op_cmps + STRINGOP_NB);
3209
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
3210
        } else if (prefixes & PREFIX_REPZ) {
3211
            if (s->cc_op != CC_OP_DYNAMIC)
3212
                gen_op_set_cc_op(s->cc_op);
3213
            gen_string_ds(s, ot, gen_op_cmps);
3214
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
3215
        } else {
3216
            gen_cmps(s, ot);
3217
            s->cc_op = CC_OP_SUBB + ot;
3218
        }
3219
        break;
3220
    case 0x6c: /* insS */
3221
    case 0x6d:
3222
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3223
            /* NOTE: even for (E)CX = 0 the exception is raised */
3224
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3225
        } else {
3226
            if ((b & 1) == 0)
3227
                ot = OT_BYTE;
3228
            else
3229
                ot = dflag ? OT_LONG : OT_WORD;
3230
            if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3231
                gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3232
            } else {
3233
                gen_ins(s, ot);
3234
            }
3235
        }
3236
        break;
3237
    case 0x6e: /* outsS */
3238
    case 0x6f:
3239
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3240
            /* NOTE: even for (E)CX = 0 the exception is raised */
3241
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3242
        } else {
3243
            if ((b & 1) == 0)
3244
                ot = OT_BYTE;
3245
            else
3246
                ot = dflag ? OT_LONG : OT_WORD;
3247
            if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3248
                gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3249
            } else {
3250
                gen_outs(s, ot);
3251
            }
3252
        }
3253
        break;
3254

    
3255
        /************************/
3256
        /* port I/O */
3257
    case 0xe4:
3258
    case 0xe5:
3259
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3260
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3261
        } else {
3262
            if ((b & 1) == 0)
3263
                ot = OT_BYTE;
3264
            else
3265
                ot = dflag ? OT_LONG : OT_WORD;
3266
            val = ldub(s->pc++);
3267
            gen_op_movl_T0_im(val);
3268
            gen_op_in[ot]();
3269
            gen_op_mov_reg_T1[ot][R_EAX]();
3270
        }
3271
        break;
3272
    case 0xe6:
3273
    case 0xe7:
3274
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3275
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3276
        } else {
3277
            if ((b & 1) == 0)
3278
                ot = OT_BYTE;
3279
            else
3280
                ot = dflag ? OT_LONG : OT_WORD;
3281
            val = ldub(s->pc++);
3282
            gen_op_movl_T0_im(val);
3283
            gen_op_mov_TN_reg[ot][1][R_EAX]();
3284
            gen_op_out[ot]();
3285
        }
3286
        break;
3287
    case 0xec:
3288
    case 0xed:
3289
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3290
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3291
        } else {
3292
            if ((b & 1) == 0)
3293
                ot = OT_BYTE;
3294
            else
3295
                ot = dflag ? OT_LONG : OT_WORD;
3296
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3297
            gen_op_in[ot]();
3298
            gen_op_mov_reg_T1[ot][R_EAX]();
3299
        }
3300
        break;
3301
    case 0xee:
3302
    case 0xef:
3303
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3304
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3305
        } else {
3306
            if ((b & 1) == 0)
3307
                ot = OT_BYTE;
3308
            else
3309
                ot = dflag ? OT_LONG : OT_WORD;
3310
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3311
            gen_op_mov_TN_reg[ot][1][R_EAX]();
3312
            gen_op_out[ot]();
3313
        }
3314
        break;
3315

    
3316
        /************************/
3317
        /* control */
3318
    case 0xc2: /* ret im */
3319
        val = ldsw(s->pc);
3320
        s->pc += 2;
3321
        gen_pop_T0(s);
3322
        gen_stack_update(s, val + (2 << s->dflag));
3323
        if (s->dflag == 0)
3324
            gen_op_andl_T0_ffff();
3325
        gen_op_jmp_T0();
3326
        s->is_jmp = 1;
3327
        break;
3328
    case 0xc3: /* ret */
3329
        gen_pop_T0(s);
3330
        gen_pop_update(s);
3331
        if (s->dflag == 0)
3332
            gen_op_andl_T0_ffff();
3333
        gen_op_jmp_T0();
3334
        s->is_jmp = 1;
3335
        break;
3336
    case 0xca: /* lret im */
3337
        val = ldsw(s->pc);
3338
        s->pc += 2;
3339
    do_lret:
3340
        if (s->pe && !s->vm86) {
3341
            if (s->cc_op != CC_OP_DYNAMIC)
3342
                gen_op_set_cc_op(s->cc_op);
3343
            gen_op_jmp_im(pc_start - s->cs_base);
3344
            gen_op_lret_protected(s->dflag, val);
3345
        } else {
3346
            gen_stack_A0(s);
3347
            /* pop offset */
3348
            gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3349
            if (s->dflag == 0)
3350
                gen_op_andl_T0_ffff();
3351
            /* NOTE: keeping EIP updated is not a problem in case of
3352
               exception */
3353
            gen_op_jmp_T0();
3354
            /* pop selector */
3355
            gen_op_addl_A0_im(2 << s->dflag);
3356
            gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3357
            gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3358
            /* add stack offset */
3359
            gen_stack_update(s, val + (4 << s->dflag));
3360
        }
3361
        s->is_jmp = 1;
3362
        break;
3363
    case 0xcb: /* lret */
3364
        val = 0;
3365
        goto do_lret;
3366
    case 0xcf: /* iret */
3367
        if (!s->pe) {
3368
            /* real mode */
3369
            gen_op_iret_real(s->dflag);
3370
            s->cc_op = CC_OP_EFLAGS;
3371
        } else if (s->vm86 && s->iopl != 3) {
3372
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3373
        } else {
3374
            if (s->cc_op != CC_OP_DYNAMIC)
3375
                gen_op_set_cc_op(s->cc_op);
3376
            gen_op_jmp_im(pc_start - s->cs_base);
3377
            gen_op_iret_protected(s->dflag);
3378
            s->cc_op = CC_OP_EFLAGS;
3379
        }
3380
        s->is_jmp = 1;
3381
        break;
3382
    case 0xe8: /* call im */
3383
        {
3384
            unsigned int next_eip;
3385
            ot = dflag ? OT_LONG : OT_WORD;
3386
            val = insn_get(s, ot);
3387
            next_eip = s->pc - s->cs_base;
3388
            val += next_eip;
3389
            if (s->dflag == 0)
3390
                val &= 0xffff;
3391
            gen_op_movl_T0_im(next_eip);
3392
            gen_push_T0(s);
3393
            gen_jmp(s, val);
3394
        }
3395
        break;
3396
    case 0x9a: /* lcall im */
3397
        {
3398
            unsigned int selector, offset;
3399

    
3400
            ot = dflag ? OT_LONG : OT_WORD;
3401
            offset = insn_get(s, ot);
3402
            selector = insn_get(s, OT_WORD);
3403
            
3404
            gen_op_movl_T0_im(selector);
3405
            gen_op_movl_T1_im(offset);
3406
        }
3407
        goto do_lcall;
3408
    case 0xe9: /* jmp */
3409
        ot = dflag ? OT_LONG : OT_WORD;
3410
        val = insn_get(s, ot);
3411
        val += s->pc - s->cs_base;
3412
        if (s->dflag == 0)
3413
            val = val & 0xffff;
3414
        gen_jmp(s, val);
3415
        break;
3416
    case 0xea: /* ljmp im */
3417
        {
3418
            unsigned int selector, offset;
3419

    
3420
            ot = dflag ? OT_LONG : OT_WORD;
3421
            offset = insn_get(s, ot);
3422
            selector = insn_get(s, OT_WORD);
3423
            
3424
            gen_op_movl_T0_im(selector);
3425
            gen_op_movl_T1_im(offset);
3426
        }
3427
        goto do_ljmp;
3428
    case 0xeb: /* jmp Jb */
3429
        val = (int8_t)insn_get(s, OT_BYTE);
3430
        val += s->pc - s->cs_base;
3431
        if (s->dflag == 0)
3432
            val = val & 0xffff;
3433
        gen_jmp(s, val);
3434
        break;
3435
    case 0x70 ... 0x7f: /* jcc Jb */
3436
        val = (int8_t)insn_get(s, OT_BYTE);
3437
        goto do_jcc;
3438
    case 0x180 ... 0x18f: /* jcc Jv */
3439
        if (dflag) {
3440
            val = insn_get(s, OT_LONG);
3441
        } else {
3442
            val = (int16_t)insn_get(s, OT_WORD); 
3443
        }
3444
    do_jcc:
3445
        next_eip = s->pc - s->cs_base;
3446
        val += next_eip;
3447
        if (s->dflag == 0)
3448
            val &= 0xffff;
3449
        gen_jcc(s, b, val, next_eip);
3450
        break;
3451

    
3452
    case 0x190 ... 0x19f: /* setcc Gv */
3453
        modrm = ldub(s->pc++);
3454
        gen_setcc(s, b);
3455
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3456
        break;
3457
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3458
        ot = dflag ? OT_LONG : OT_WORD;
3459
        modrm = ldub(s->pc++);
3460
        reg = (modrm >> 3) & 7;
3461
        mod = (modrm >> 6) & 3;
3462
        gen_setcc(s, b);
3463
        if (mod != 3) {
3464
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3465
            gen_op_ld_T1_A0[ot + s->mem_index]();
3466
        } else {
3467
            rm = modrm & 7;
3468
            gen_op_mov_TN_reg[ot][1][rm]();
3469
        }
3470
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3471
        break;
3472
        
3473
        /************************/
3474
        /* flags */
3475
    case 0x9c: /* pushf */
3476
        if (s->vm86 && s->iopl != 3) {
3477
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3478
        } else {
3479
            if (s->cc_op != CC_OP_DYNAMIC)
3480
                gen_op_set_cc_op(s->cc_op);
3481
            gen_op_movl_T0_eflags();
3482
            gen_push_T0(s);
3483
        }
3484
        break;
3485
    case 0x9d: /* popf */
3486
        if (s->vm86 && s->iopl != 3) {
3487
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3488
        } else {
3489
            gen_pop_T0(s);
3490
            if (s->cpl == 0) {
3491
                if (s->dflag) {
3492
                    gen_op_movl_eflags_T0_cpl0();
3493
                } else {
3494
                    gen_op_movw_eflags_T0_cpl0();
3495
                }
3496
            } else {
3497
                if (s->dflag) {
3498
                    gen_op_movl_eflags_T0();
3499
                } else {
3500
                    gen_op_movw_eflags_T0();
3501
                }
3502
            }
3503
            gen_pop_update(s);
3504
            s->cc_op = CC_OP_EFLAGS;
3505
            s->is_jmp = 2; /* abort translation because TF flag may change */
3506
        }
3507
        break;
3508
    case 0x9e: /* sahf */
3509
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3510
        if (s->cc_op != CC_OP_DYNAMIC)
3511
            gen_op_set_cc_op(s->cc_op);
3512
        gen_op_movb_eflags_T0();
3513
        s->cc_op = CC_OP_EFLAGS;
3514
        break;
3515
    case 0x9f: /* lahf */
3516
        if (s->cc_op != CC_OP_DYNAMIC)
3517
            gen_op_set_cc_op(s->cc_op);
3518
        gen_op_movl_T0_eflags();
3519
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3520
        break;
3521
    case 0xf5: /* cmc */
3522
        if (s->cc_op != CC_OP_DYNAMIC)
3523
            gen_op_set_cc_op(s->cc_op);
3524
        gen_op_cmc();
3525
        s->cc_op = CC_OP_EFLAGS;
3526
        break;
3527
    case 0xf8: /* clc */
3528
        if (s->cc_op != CC_OP_DYNAMIC)
3529
            gen_op_set_cc_op(s->cc_op);
3530
        gen_op_clc();
3531
        s->cc_op = CC_OP_EFLAGS;
3532
        break;
3533
    case 0xf9: /* stc */
3534
        if (s->cc_op != CC_OP_DYNAMIC)
3535
            gen_op_set_cc_op(s->cc_op);
3536
        gen_op_stc();
3537
        s->cc_op = CC_OP_EFLAGS;
3538
        break;
3539
    case 0xfc: /* cld */
3540
        gen_op_cld();
3541
        break;
3542
    case 0xfd: /* std */
3543
        gen_op_std();
3544
        break;
3545

    
3546
        /************************/
3547
        /* bit operations */
3548
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
3549
        ot = dflag ? OT_LONG : OT_WORD;
3550
        modrm = ldub(s->pc++);
3551
        op = (modrm >> 3) & 7;
3552
        mod = (modrm >> 6) & 3;
3553
        rm = modrm & 7;
3554
        if (mod != 3) {
3555
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3556
            gen_op_ld_T0_A0[ot + s->mem_index]();
3557
        } else {
3558
            gen_op_mov_TN_reg[ot][0][rm]();
3559
        }
3560
        /* load shift */
3561
        val = ldub(s->pc++);
3562
        gen_op_movl_T1_im(val);
3563
        if (op < 4)
3564
            goto illegal_op;
3565
        op -= 4;
3566
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3567
        s->cc_op = CC_OP_SARB + ot;
3568
        if (op != 0) {
3569
            if (mod != 3)
3570
                gen_op_st_T0_A0[ot + s->mem_index]();
3571
            else
3572
                gen_op_mov_reg_T0[ot][rm]();
3573
            gen_op_update_bt_cc();
3574
        }
3575
        break;
3576
    case 0x1a3: /* bt Gv, Ev */
3577
        op = 0;
3578
        goto do_btx;
3579
    case 0x1ab: /* bts */
3580
        op = 1;
3581
        goto do_btx;
3582
    case 0x1b3: /* btr */
3583
        op = 2;
3584
        goto do_btx;
3585
    case 0x1bb: /* btc */
3586
        op = 3;
3587
    do_btx:
3588
        ot = dflag ? OT_LONG : OT_WORD;
3589
        modrm = ldub(s->pc++);
3590
        reg = (modrm >> 3) & 7;
3591
        mod = (modrm >> 6) & 3;
3592
        rm = modrm & 7;
3593
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3594
        if (mod != 3) {
3595
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3596
            /* specific case: we need to add a displacement */
3597
            if (ot == OT_WORD)
3598
                gen_op_add_bitw_A0_T1();
3599
            else
3600
                gen_op_add_bitl_A0_T1();
3601
            gen_op_ld_T0_A0[ot + s->mem_index]();
3602
        } else {
3603
            gen_op_mov_TN_reg[ot][0][rm]();
3604
        }
3605
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3606
        s->cc_op = CC_OP_SARB + ot;
3607
        if (op != 0) {
3608
            if (mod != 3)
3609
                gen_op_st_T0_A0[ot + s->mem_index]();
3610
            else
3611
                gen_op_mov_reg_T0[ot][rm]();
3612
            gen_op_update_bt_cc();
3613
        }
3614
        break;
3615
    case 0x1bc: /* bsf */
3616
    case 0x1bd: /* bsr */
3617
        ot = dflag ? OT_LONG : OT_WORD;
3618
        modrm = ldub(s->pc++);
3619
        reg = (modrm >> 3) & 7;
3620
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3621
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3622
        /* NOTE: we always write back the result. Intel doc says it is
3623
           undefined if T0 == 0 */
3624
        gen_op_mov_reg_T0[ot][reg]();
3625
        s->cc_op = CC_OP_LOGICB + ot;
3626
        break;
3627
        /************************/
3628
        /* bcd */
3629
    case 0x27: /* daa */
3630
        if (s->cc_op != CC_OP_DYNAMIC)
3631
            gen_op_set_cc_op(s->cc_op);
3632
        gen_op_daa();
3633
        s->cc_op = CC_OP_EFLAGS;
3634
        break;
3635
    case 0x2f: /* das */
3636
        if (s->cc_op != CC_OP_DYNAMIC)
3637
            gen_op_set_cc_op(s->cc_op);
3638
        gen_op_das();
3639
        s->cc_op = CC_OP_EFLAGS;
3640
        break;
3641
    case 0x37: /* aaa */
3642
        if (s->cc_op != CC_OP_DYNAMIC)
3643
            gen_op_set_cc_op(s->cc_op);
3644
        gen_op_aaa();
3645
        s->cc_op = CC_OP_EFLAGS;
3646
        break;
3647
    case 0x3f: /* aas */
3648
        if (s->cc_op != CC_OP_DYNAMIC)
3649
            gen_op_set_cc_op(s->cc_op);
3650
        gen_op_aas();
3651
        s->cc_op = CC_OP_EFLAGS;
3652
        break;
3653
    case 0xd4: /* aam */
3654
        val = ldub(s->pc++);
3655
        gen_op_aam(val);
3656
        s->cc_op = CC_OP_LOGICB;
3657
        break;
3658
    case 0xd5: /* aad */
3659
        val = ldub(s->pc++);
3660
        gen_op_aad(val);
3661
        s->cc_op = CC_OP_LOGICB;
3662
        break;
3663
        /************************/
3664
        /* misc */
3665
    case 0x90: /* nop */
3666
        break;
3667
    case 0x9b: /* fwait */
3668
        break;
3669
    case 0xcc: /* int3 */
3670
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3671
        break;
3672
    case 0xcd: /* int N */
3673
        val = ldub(s->pc++);
3674
        /* XXX: add error code for vm86 GPF */
3675
        if (!s->vm86)
3676
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3677
        else
3678
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
3679
        break;
3680
    case 0xce: /* into */
3681
        if (s->cc_op != CC_OP_DYNAMIC)
3682
            gen_op_set_cc_op(s->cc_op);
3683
        gen_op_into(s->pc - s->cs_base);
3684
        break;
3685
    case 0xf1: /* icebp (undocumented, exits to external debugger) */
3686
        gen_debug(s, pc_start - s->cs_base);
3687
        break;
3688
    case 0xfa: /* cli */
3689
        if (!s->vm86) {
3690
            if (s->cpl <= s->iopl) {
3691
                gen_op_cli();
3692
            } else {
3693
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3694
            }
3695
        } else {
3696
            if (s->iopl == 3) {
3697
                gen_op_cli();
3698
            } else {
3699
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3700
            }
3701
        }
3702
        break;
3703
    case 0xfb: /* sti */
3704
        if (!s->vm86) {
3705
            if (s->cpl <= s->iopl) {
3706
                gen_op_sti();
3707
                s->is_jmp = 2; /* give a chance to handle pending irqs */
3708
            } else {
3709
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3710
            }
3711
        } else {
3712
            if (s->iopl == 3) {
3713
                gen_op_sti();
3714
                s->is_jmp = 2; /* give a chance to handle pending irqs */
3715
            } else {
3716
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3717
            }
3718
        }
3719
        /* XXX: interruptions are enabled only the first insn after sti */
3720
        break;
3721
    case 0x62: /* bound */
3722
        ot = dflag ? OT_LONG : OT_WORD;
3723
        modrm = ldub(s->pc++);
3724
        reg = (modrm >> 3) & 7;
3725
        mod = (modrm >> 6) & 3;
3726
        if (mod == 3)
3727
            goto illegal_op;
3728
        gen_op_mov_reg_T0[ot][reg]();
3729
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3730
        if (ot == OT_WORD)
3731
            gen_op_boundw(pc_start - s->cs_base);
3732
        else
3733
            gen_op_boundl(pc_start - s->cs_base);
3734
        break;
3735
    case 0x1c8 ... 0x1cf: /* bswap reg */
3736
        reg = b & 7;
3737
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3738
        gen_op_bswapl_T0();
3739
        gen_op_mov_reg_T0[OT_LONG][reg]();
3740
        break;
3741
    case 0xd6: /* salc */
3742
        if (s->cc_op != CC_OP_DYNAMIC)
3743
            gen_op_set_cc_op(s->cc_op);
3744
        gen_op_salc();
3745
        break;
3746
    case 0xe0: /* loopnz */
3747
    case 0xe1: /* loopz */
3748
        if (s->cc_op != CC_OP_DYNAMIC)
3749
            gen_op_set_cc_op(s->cc_op);
3750
        /* FALL THRU */
3751
    case 0xe2: /* loop */
3752
    case 0xe3: /* jecxz */
3753
        val = (int8_t)insn_get(s, OT_BYTE);
3754
        next_eip = s->pc - s->cs_base;
3755
        val += next_eip;
3756
        if (s->dflag == 0)
3757
            val &= 0xffff;
3758
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3759
        s->is_jmp = 1;
3760
        break;
3761
    case 0x130: /* wrmsr */
3762
    case 0x132: /* rdmsr */
3763
        if (s->cpl != 0) {
3764
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3765
        } else {
3766
            if (b & 2)
3767
                gen_op_rdmsr();
3768
            else
3769
                gen_op_wrmsr();
3770
        }
3771
        break;
3772
    case 0x131: /* rdtsc */
3773
        gen_op_rdtsc();
3774
        break;
3775
    case 0x1a2: /* cpuid */
3776
        gen_op_cpuid();
3777
        break;
3778
    case 0xf4: /* hlt */
3779
        if (s->cpl != 0) {
3780
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3781
        } else {
3782
            if (s->cc_op != CC_OP_DYNAMIC)
3783
                gen_op_set_cc_op(s->cc_op);
3784
            gen_op_jmp_im(s->pc - s->cs_base);
3785
            gen_op_hlt();
3786
            s->is_jmp = 1;
3787
        }
3788
        break;
3789
    case 0x100:
3790
        modrm = ldub(s->pc++);
3791
        mod = (modrm >> 6) & 3;
3792
        op = (modrm >> 3) & 7;
3793
        switch(op) {
3794
        case 0: /* sldt */
3795
            gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3796
            ot = OT_WORD;
3797
            if (mod == 3)
3798
                ot += s->dflag;
3799
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3800
            break;
3801
        case 2: /* lldt */
3802
            if (s->cpl != 0) {
3803
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3804
            } else {
3805
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3806
                gen_op_jmp_im(pc_start - s->cs_base);
3807
                gen_op_lldt_T0();
3808
            }
3809
            break;
3810
        case 1: /* str */
3811
            gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3812
            ot = OT_WORD;
3813
            if (mod == 3)
3814
                ot += s->dflag;
3815
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3816
            break;
3817
        case 3: /* ltr */
3818
            if (s->cpl != 0) {
3819
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3820
            } else {
3821
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3822
                gen_op_jmp_im(pc_start - s->cs_base);
3823
                gen_op_ltr_T0();
3824
            }
3825
            break;
3826
        case 4: /* verr */
3827
        case 5: /* verw */
3828
        default:
3829
            goto illegal_op;
3830
        }
3831
        break;
3832
    case 0x101:
3833
        modrm = ldub(s->pc++);
3834
        mod = (modrm >> 6) & 3;
3835
        op = (modrm >> 3) & 7;
3836
        switch(op) {
3837
        case 0: /* sgdt */
3838
        case 1: /* sidt */
3839
            if (mod == 3)
3840
                goto illegal_op;
3841
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3842
            if (op == 0)
3843
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3844
            else
3845
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3846
            gen_op_st_T0_A0[OT_WORD + s->mem_index]();
3847
            gen_op_addl_A0_im(2);
3848
            if (op == 0)
3849
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3850
            else
3851
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3852
            if (!s->dflag)
3853
                gen_op_andl_T0_im(0xffffff);
3854
            gen_op_st_T0_A0[OT_LONG + s->mem_index]();
3855
            break;
3856
        case 2: /* lgdt */
3857
        case 3: /* lidt */
3858
            if (mod == 3)
3859
                goto illegal_op;
3860
            if (s->cpl != 0) {
3861
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3862
            } else {
3863
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3864
                gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
3865
                gen_op_addl_A0_im(2);
3866
                gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3867
                if (!s->dflag)
3868
                    gen_op_andl_T0_im(0xffffff);
3869
                if (op == 2) {
3870
                    gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3871
                    gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3872
                } else {
3873
                    gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3874
                    gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3875
                }
3876
            }
3877
            break;
3878
        case 4: /* smsw */
3879
            gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3880
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3881
            break;
3882
        case 6: /* lmsw */
3883
            if (s->cpl != 0) {
3884
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3885
            } else {
3886
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3887
                gen_op_lmsw_T0();
3888
            }
3889
            break;
3890
        case 7: /* invlpg */
3891
            if (s->cpl != 0) {
3892
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3893
            } else {
3894
                if (mod == 3)
3895
                    goto illegal_op;
3896
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3897
                gen_op_invlpg_A0();
3898
            }
3899
            break;
3900
        default:
3901
            goto illegal_op;
3902
        }
3903
        break;
3904
    case 0x102: /* lar */
3905
    case 0x103: /* lsl */
3906
        if (!s->pe || s->vm86)
3907
            goto illegal_op;
3908
        ot = dflag ? OT_LONG : OT_WORD;
3909
        modrm = ldub(s->pc++);
3910
        reg = (modrm >> 3) & 7;
3911
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3912
        gen_op_mov_TN_reg[ot][1][reg]();
3913
        if (s->cc_op != CC_OP_DYNAMIC)
3914
            gen_op_set_cc_op(s->cc_op);
3915
        if (b == 0x102)
3916
            gen_op_lar();
3917
        else
3918
            gen_op_lsl();
3919
        s->cc_op = CC_OP_EFLAGS;
3920
        gen_op_mov_reg_T1[ot][reg]();
3921
        break;
3922
    case 0x118:
3923
        modrm = ldub(s->pc++);
3924
        mod = (modrm >> 6) & 3;
3925
        op = (modrm >> 3) & 7;
3926
        switch(op) {
3927
        case 0: /* prefetchnta */
3928
        case 1: /* prefetchnt0 */
3929
        case 2: /* prefetchnt0 */
3930
        case 3: /* prefetchnt0 */
3931
            if (mod == 3)
3932
                goto illegal_op;
3933
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3934
            /* nothing more to do */
3935
            break;
3936
        default:
3937
            goto illegal_op;
3938
        }
3939
        break;
3940
    case 0x120: /* mov reg, crN */
3941
    case 0x122: /* mov crN, reg */
3942
        if (s->cpl != 0) {
3943
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3944
        } else {
3945
            modrm = ldub(s->pc++);
3946
            if ((modrm & 0xc0) != 0xc0)
3947
                goto illegal_op;
3948
            rm = modrm & 7;
3949
            reg = (modrm >> 3) & 7;
3950
            switch(reg) {
3951
            case 0:
3952
            case 2:
3953
            case 3:
3954
            case 4:
3955
                if (b & 2) {
3956
                    gen_op_mov_TN_reg[OT_LONG][0][rm]();
3957
                    gen_op_movl_crN_T0(reg);
3958
                    s->is_jmp = 2;
3959
                } else {
3960
                    gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3961
                    gen_op_mov_reg_T0[OT_LONG][rm]();
3962
                }
3963
                break;
3964
            default:
3965
                goto illegal_op;
3966
            }
3967
        }
3968
        break;
3969
    case 0x121: /* mov reg, drN */
3970
    case 0x123: /* mov drN, reg */
3971
        if (s->cpl != 0) {
3972
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3973
        } else {
3974
            modrm = ldub(s->pc++);
3975
            if ((modrm & 0xc0) != 0xc0)
3976
                goto illegal_op;
3977
            rm = modrm & 7;
3978
            reg = (modrm >> 3) & 7;
3979
            /* XXX: do it dynamically with CR4.DE bit */
3980
            if (reg == 4 || reg == 5)
3981
                goto illegal_op;
3982
            if (b & 2) {
3983
                gen_op_mov_TN_reg[OT_LONG][0][rm]();
3984
                gen_op_movl_drN_T0(reg);
3985
                s->is_jmp = 2;
3986
            } else {
3987
                gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3988
                gen_op_mov_reg_T0[OT_LONG][rm]();
3989
            }
3990
        }
3991
        break;
3992
    case 0x106: /* clts */
3993
        if (s->cpl != 0) {
3994
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3995
        } else {
3996
            gen_op_clts();
3997
        }
3998
        break;
3999
    default:
4000
        goto illegal_op;
4001
    }
4002
    /* lock generation */
4003
    if (s->prefix & PREFIX_LOCK)
4004
        gen_op_unlock();
4005
    return (long)s->pc;
4006
 illegal_op:
4007
    /* XXX: ensure that no lock was generated */
4008
    return -1;
4009
}
4010

    
4011
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
4012
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
4013

    
4014
/* flags read by an operation */
4015
static uint16_t opc_read_flags[NB_OPS] = { 
4016
    [INDEX_op_aas] = CC_A,
4017
    [INDEX_op_aaa] = CC_A,
4018
    [INDEX_op_das] = CC_A | CC_C,
4019
    [INDEX_op_daa] = CC_A | CC_C,
4020

    
4021
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
4022
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
4023
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
4024
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
4025
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
4026
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
4027

    
4028
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
4029
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
4030
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
4031
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
4032
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
4033
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
4034

    
4035
    /* subtle: due to the incl/decl implementation, C is used */
4036
    [INDEX_op_update_inc_cc] = CC_C, 
4037

    
4038
    [INDEX_op_into] = CC_O,
4039

    
4040
    [INDEX_op_jb_subb] = CC_C,
4041
    [INDEX_op_jb_subw] = CC_C,
4042
    [INDEX_op_jb_subl] = CC_C,
4043

    
4044
    [INDEX_op_jz_subb] = CC_Z,
4045
    [INDEX_op_jz_subw] = CC_Z,
4046
    [INDEX_op_jz_subl] = CC_Z,
4047

    
4048
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
4049
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
4050
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
4051

    
4052
    [INDEX_op_js_subb] = CC_S,
4053
    [INDEX_op_js_subw] = CC_S,
4054
    [INDEX_op_js_subl] = CC_S,
4055

    
4056
    [INDEX_op_jl_subb] = CC_O | CC_S,
4057
    [INDEX_op_jl_subw] = CC_O | CC_S,
4058
    [INDEX_op_jl_subl] = CC_O | CC_S,
4059

    
4060
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
4061
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
4062
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
4063

    
4064
    [INDEX_op_loopnzw] = CC_Z,
4065
    [INDEX_op_loopnzl] = CC_Z,
4066
    [INDEX_op_loopzw] = CC_Z,
4067
    [INDEX_op_loopzl] = CC_Z,
4068

    
4069
    [INDEX_op_seto_T0_cc] = CC_O,
4070
    [INDEX_op_setb_T0_cc] = CC_C,
4071
    [INDEX_op_setz_T0_cc] = CC_Z,
4072
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
4073
    [INDEX_op_sets_T0_cc] = CC_S,
4074
    [INDEX_op_setp_T0_cc] = CC_P,
4075
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
4076
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
4077

    
4078
    [INDEX_op_setb_T0_subb] = CC_C,
4079
    [INDEX_op_setb_T0_subw] = CC_C,
4080
    [INDEX_op_setb_T0_subl] = CC_C,
4081

    
4082
    [INDEX_op_setz_T0_subb] = CC_Z,
4083
    [INDEX_op_setz_T0_subw] = CC_Z,
4084
    [INDEX_op_setz_T0_subl] = CC_Z,
4085

    
4086
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
4087
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
4088
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
4089

    
4090
    [INDEX_op_sets_T0_subb] = CC_S,
4091
    [INDEX_op_sets_T0_subw] = CC_S,
4092
    [INDEX_op_sets_T0_subl] = CC_S,
4093

    
4094
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
4095
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
4096
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
4097

    
4098
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
4099
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
4100
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
4101

    
4102
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
4103
    [INDEX_op_cmc] = CC_C,
4104
    [INDEX_op_salc] = CC_C,
4105

    
4106
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
4107
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
4108
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
4109
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
4110
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
4111
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
4112

    
4113
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
4114
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
4115
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
4116
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
4117
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
4118
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
4119
};
4120

    
4121
/* flags written by an operation */
4122
static uint16_t opc_write_flags[NB_OPS] = { 
4123
    [INDEX_op_update2_cc] = CC_OSZAPC,
4124
    [INDEX_op_update1_cc] = CC_OSZAPC,
4125
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
4126
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
4127
    /* subtle: due to the incl/decl implementation, C is used */
4128
    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
4129
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
4130

    
4131
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
4132
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
4133
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
4134
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
4135
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
4136
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
4137

    
4138
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
4139
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
4140
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
4141
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
4142
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
4143
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
4144

    
4145
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
4146
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
4147
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
4148
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
4149
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
4150
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
4151
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
4152
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
4153
    
4154
    /* bcd */
4155
    [INDEX_op_aam] = CC_OSZAPC,
4156
    [INDEX_op_aad] = CC_OSZAPC,
4157
    [INDEX_op_aas] = CC_OSZAPC,
4158
    [INDEX_op_aaa] = CC_OSZAPC,
4159
    [INDEX_op_das] = CC_OSZAPC,
4160
    [INDEX_op_daa] = CC_OSZAPC,
4161

    
4162
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
4163
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
4164
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4165
    [INDEX_op_clc] = CC_C,
4166
    [INDEX_op_stc] = CC_C,
4167
    [INDEX_op_cmc] = CC_C,
4168

    
4169
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
4170
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
4171
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
4172
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
4173
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
4174
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
4175

    
4176
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
4177
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
4178
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
4179
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
4180
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
4181
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
4182

    
4183
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
4184
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
4185
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
4186

    
4187
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
4188
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
4189
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
4190

    
4191
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
4192
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
4193
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
4194

    
4195
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
4196
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
4197
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
4198
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
4199

    
4200
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
4201
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
4202
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
4203
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
4204

    
4205
    [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
4206
    [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
4207
    [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
4208
    [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
4209
    [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
4210
    [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
4211

    
4212
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
4213
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
4214
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
4215
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
4216
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
4217
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
4218

    
4219
    [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
4220
    [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
4221
    [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
4222

    
4223
    [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
4224
    [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
4225
    [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
4226

    
4227
    [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
4228
    [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
4229
    [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
4230

    
4231
    [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4232
    [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4233
    [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
4234
    [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
4235

    
4236
    [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4237
    [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4238
    [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
4239
    [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
4240

    
4241
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
4242
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
4243
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
4244
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
4245
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
4246
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
4247
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
4248
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
4249

    
4250
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
4251
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
4252
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4253
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4254

    
4255
#undef STRINGOP
4256
#define STRINGOP(x) \
4257
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
4258
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
4259
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
4260
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
4261
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
4262
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
4263
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
4264
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
4265
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
4266

    
4267
    STRINGOP(repz_scas)
4268
    STRINGOP(repnz_scas)
4269
    STRINGOP(repz_cmps)
4270
    STRINGOP(repnz_cmps)
4271

    
4272
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4273
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4274
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4275

    
4276
    [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4277
    [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4278
    [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4279

    
4280
    [INDEX_op_cmpxchg8b] = CC_Z,
4281
    [INDEX_op_lar] = CC_Z,
4282
    [INDEX_op_lsl] = CC_Z,
4283
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4284
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4285
};
4286

    
4287
/* simpler form of an operation if no flags need to be generated */
4288
static uint16_t opc_simpler[NB_OPS] = { 
4289
    [INDEX_op_update2_cc] = INDEX_op_nop,
4290
    [INDEX_op_update1_cc] = INDEX_op_nop,
4291
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
4292
#if 0
4293
    /* broken: CC_OP logic must be rewritten */
4294
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
4295
#endif
4296
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
4297
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
4298
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
4299

    
4300
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
4301
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
4302
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
4303

    
4304
    [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
4305
    [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
4306
    [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
4307

    
4308
    [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
4309
    [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
4310
    [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
4311

    
4312
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4313
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4314
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4315

    
4316
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4317
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4318
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4319

    
4320
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4321
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4322
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4323
};
4324

    
4325
void optimize_flags_init(void)
4326
{
4327
    int i;
4328
    /* put default values in arrays */
4329
    for(i = 0; i < NB_OPS; i++) {
4330
        if (opc_simpler[i] == 0)
4331
            opc_simpler[i] = i;
4332
    }
4333
}
4334

    
4335
/* CPU flags computation optimization: we move backward thru the
4336
   generated code to see which flags are needed. The operation is
4337
   modified if suitable */
4338
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4339
{
4340
    uint16_t *opc_ptr;
4341
    int live_flags, write_flags, op;
4342

    
4343
    opc_ptr = opc_buf + opc_buf_len;
4344
    /* live_flags contains the flags needed by the next instructions
4345
       in the code. At the end of the bloc, we consider that all the
4346
       flags are live. */
4347
    live_flags = CC_OSZAPC;
4348
    while (opc_ptr > opc_buf) {
4349
        op = *--opc_ptr;
4350
        /* if none of the flags written by the instruction is used,
4351
           then we can try to find a simpler instruction */
4352
        write_flags = opc_write_flags[op];
4353
        if ((live_flags & write_flags) == 0) {
4354
            *opc_ptr = opc_simpler[op];
4355
        }
4356
        /* compute the live flags before the instruction */
4357
        live_flags &= ~write_flags;
4358
        live_flags |= opc_read_flags[op];
4359
    }
4360
}
4361

    
4362
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4363
   basic block 'tb'. If search_pc is TRUE, also generate PC
4364
   information for each intermediate instruction. */
4365
static inline int gen_intermediate_code_internal(CPUState *env,
4366
                                                 TranslationBlock *tb, 
4367
                                                 int search_pc)
4368
{
4369
    DisasContext dc1, *dc = &dc1;
4370
    uint8_t *pc_ptr;
4371
    uint16_t *gen_opc_end;
4372
    int flags, j, lj;
4373
    long ret;
4374
    uint8_t *pc_start;
4375
    uint8_t *cs_base;
4376
    
4377
    /* generate intermediate code */
4378
    pc_start = (uint8_t *)tb->pc;
4379
    cs_base = (uint8_t *)tb->cs_base;
4380
    flags = tb->flags;
4381
       
4382
    dc->pe = env->cr[0] & CR0_PE_MASK;
4383
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
4384
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
4385
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
4386
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
4387
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
4388
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4389
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
4390
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
4391
    dc->cc_op = CC_OP_DYNAMIC;
4392
    dc->cs_base = cs_base;
4393
    dc->tb = tb;
4394
    dc->popl_esp_hack = 0;
4395
    /* select memory access functions */
4396
    dc->mem_index = 0;
4397
    if ((flags >> GEN_FLAG_SOFT_MMU_SHIFT) & 1) {
4398
        if (dc->cpl == 3)
4399
            dc->mem_index = 6;
4400
        else
4401
            dc->mem_index = 3;
4402
    }
4403

    
4404
    gen_opc_ptr = gen_opc_buf;
4405
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4406
    gen_opparam_ptr = gen_opparam_buf;
4407

    
4408
    dc->is_jmp = DISAS_NEXT;
4409
    pc_ptr = pc_start;
4410
    lj = -1;
4411
    do {
4412
        if (env->nb_breakpoints > 0) {
4413
            for(j = 0; j < env->nb_breakpoints; j++) {
4414
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4415
                    gen_debug(dc, pc_ptr - dc->cs_base);
4416
                    goto the_end;
4417
                }
4418
            }
4419
        }
4420
        if (search_pc) {
4421
            j = gen_opc_ptr - gen_opc_buf;
4422
            if (lj < j) {
4423
                lj++;
4424
                while (lj < j)
4425
                    gen_opc_instr_start[lj++] = 0;
4426
            }
4427
            gen_opc_pc[lj] = (uint32_t)pc_ptr;
4428
            gen_opc_cc_op[lj] = dc->cc_op;
4429
            gen_opc_instr_start[lj] = 1;
4430
        }
4431
        ret = disas_insn(dc, pc_ptr);
4432
        if (ret == -1) {
4433
            /* we trigger an illegal instruction operation only if it
4434
               is the first instruction. Otherwise, we simply stop
4435
               generating the code just before it */
4436
            if (pc_ptr == pc_start)
4437
                return -1;
4438
            else
4439
                break;
4440
        }
4441
        pc_ptr = (void *)ret;
4442
        /* if single step mode, we generate only one instruction and
4443
           generate an exception */
4444
        if (dc->tf)
4445
            break;
4446
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
4447
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4448
    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4449
        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4450
    }
4451

    
4452
    /* we must store the eflags state if it is not already done */
4453
    if (dc->is_jmp != DISAS_TB_JUMP) {
4454
        if (dc->cc_op != CC_OP_DYNAMIC)
4455
            gen_op_set_cc_op(dc->cc_op);
4456
        if (dc->is_jmp != DISAS_JUMP) {
4457
            /* we add an additionnal jmp to update the simulated PC */
4458
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4459
        }
4460
    }
4461
    if (dc->tf) {
4462
        gen_op_raise_exception(EXCP01_SSTP);
4463
    }
4464
 the_end:
4465
    if (dc->is_jmp != DISAS_TB_JUMP) {
4466
        /* indicate that the hash table must be used to find the next TB */
4467
        gen_op_movl_T0_0();
4468
        gen_op_exit_tb();
4469
    }
4470
    *gen_opc_ptr = INDEX_op_end;
4471
    /* we don't forget to fill the last values */
4472
    if (search_pc) {
4473
        j = gen_opc_ptr - gen_opc_buf;
4474
        lj++;
4475
        while (lj <= j)
4476
            gen_opc_instr_start[lj++] = 0;
4477
    }
4478
        
4479
#ifdef DEBUG_DISAS
4480
    if (loglevel) {
4481
        fprintf(logfile, "----------------\n");
4482
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4483
        disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4484
        fprintf(logfile, "\n");
4485

    
4486
        fprintf(logfile, "OP:\n");
4487
        dump_ops(gen_opc_buf, gen_opparam_buf);
4488
        fprintf(logfile, "\n");
4489
    }
4490
#endif
4491

    
4492
    /* optimize flag computations */
4493
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4494

    
4495
#ifdef DEBUG_DISAS
4496
    if (loglevel) {
4497
        fprintf(logfile, "AFTER FLAGS OPT:\n");
4498
        dump_ops(gen_opc_buf, gen_opparam_buf);
4499
        fprintf(logfile, "\n");
4500
    }
4501
#endif
4502
    if (!search_pc)
4503
        tb->size = pc_ptr - pc_start;
4504
    return 0;
4505
}
4506

    
4507
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4508
{
4509
    return gen_intermediate_code_internal(env, tb, 0);
4510
}
4511

    
4512
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4513
{
4514
    return gen_intermediate_code_internal(env, tb, 1);
4515
}
4516