Statistics
| Branch: | Revision:

root / translate-i386.c @ facc68be

History | View | Annotate | Download (127.2 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. Never
1548
   call this function with seg_reg == R_CS */
1549
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1550
{
1551
    if (s->pe && !s->vm86)
1552
        gen_op_movl_seg_T0(seg_reg, cur_eip);
1553
    else
1554
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1555
    /* abort translation because the register may have a non zero base
1556
       or because ss32 may change. For R_SS, translation must always
1557
       stop as a special handling must be done to disable hardware
1558
       interrupts for the next instruction */
1559
    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1560
        s->is_jmp = 2; 
1561
}
1562

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

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

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

    
1628
static void gen_pop_update(DisasContext *s)
1629
{
1630
    gen_stack_update(s, 2 << s->dflag);
1631
}
1632

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

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

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

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

    
1690
    ot = s->dflag + OT_WORD;
1691
    level &= 0x1f;
1692
    level1 = level;
1693
    opsize = 2 << s->dflag;
1694

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

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

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

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

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

    
1760
    if (s->cc_op != CC_OP_DYNAMIC)
1761
        gen_op_set_cc_op(s->cc_op);
1762
    gen_op_jmp_tb_next((long)tb, eip);
1763
    s->is_jmp = 3;
1764
}
1765

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

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

    
1821
    if (prefixes & PREFIX_DATA)
1822
        dflag ^= 1;
1823
    if (prefixes & PREFIX_ADR)
1824
        aflag ^= 1;
1825

    
1826
    s->prefix = prefixes;
1827
    s->aflag = aflag;
1828
    s->dflag = dflag;
1829

    
1830
    /* lock generation */
1831
    if (prefixes & PREFIX_LOCK)
1832
        gen_op_lock();
1833

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

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

    
1910
    case 0x80: /* GRP1 */
1911
    case 0x81:
1912
    case 0x83:
1913
        {
1914
            int val;
1915

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2665
            /* simpler op */
2666
            if (shift == 0) {
2667
                gen_shift(s, op, ot, opreg, OR_ECX);
2668
            } else {
2669
                if (shift == 2) {
2670
                    shift = ldub(s->pc++);
2671
                }
2672
                gen_shifti(s, op, ot, opreg, shift);
2673
            }
2674
        }
2675
        break;
2676
    case 0xd0:
2677
    case 0xd1:
2678
        /* shift Ev,1 */
2679
        shift = 1;
2680
        goto grp2;
2681
    case 0xd2:
2682
    case 0xd3:
2683
        /* shift Ev,cl */
2684
        shift = 0;
2685
        goto grp2;
2686

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

    
2744
        /************************/
2745
        /* floats */
2746
    case 0xd8 ... 0xdf: 
2747
        modrm = ldub(s->pc++);
2748
        mod = (modrm >> 6) & 3;
2749
        rm = modrm & 7;
2750
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2751
        
2752
        if (mod != 3) {
2753
            /* memory op */
2754
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2755
            switch(op) {
2756
            case 0x00 ... 0x07: /* fxxxs */
2757
            case 0x10 ... 0x17: /* fixxxl */
2758
            case 0x20 ... 0x27: /* fxxxl */
2759
            case 0x30 ... 0x37: /* fixxx */
2760
                {
2761
                    int op1;
2762
                    op1 = op & 7;
2763

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

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

    
3148
    case 0xa4: /* movsS */
3149
    case 0xa5:
3150
        if ((b & 1) == 0)
3151
            ot = OT_BYTE;
3152
        else
3153
            ot = dflag ? OT_LONG : OT_WORD;
3154

    
3155
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3156
            gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3157
        } else {
3158
            gen_movs(s, ot);
3159
        }
3160
        break;
3161
        
3162
    case 0xaa: /* stosS */
3163
    case 0xab:
3164
        if ((b & 1) == 0)
3165
            ot = OT_BYTE;
3166
        else
3167
            ot = dflag ? OT_LONG : OT_WORD;
3168

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

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

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

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

    
3410
            ot = dflag ? OT_LONG : OT_WORD;
3411
            offset = insn_get(s, ot);
3412
            selector = insn_get(s, OT_WORD);
3413
            
3414
            gen_op_movl_T0_im(selector);
3415
            gen_op_movl_T1_im(offset);
3416
        }
3417
        goto do_lcall;
3418
    case 0xe9: /* jmp */
3419
        ot = dflag ? OT_LONG : OT_WORD;
3420
        val = insn_get(s, ot);
3421
        val += s->pc - s->cs_base;
3422
        if (s->dflag == 0)
3423
            val = val & 0xffff;
3424
        gen_jmp(s, val);
3425
        break;
3426
    case 0xea: /* ljmp im */
3427
        {
3428
            unsigned int selector, offset;
3429

    
3430
            ot = dflag ? OT_LONG : OT_WORD;
3431
            offset = insn_get(s, ot);
3432
            selector = insn_get(s, OT_WORD);
3433
            
3434
            gen_op_movl_T0_im(selector);
3435
            gen_op_movl_T1_im(offset);
3436
        }
3437
        goto do_ljmp;
3438
    case 0xeb: /* jmp Jb */
3439
        val = (int8_t)insn_get(s, OT_BYTE);
3440
        val += s->pc - s->cs_base;
3441
        if (s->dflag == 0)
3442
            val = val & 0xffff;
3443
        gen_jmp(s, val);
3444
        break;
3445
    case 0x70 ... 0x7f: /* jcc Jb */
3446
        val = (int8_t)insn_get(s, OT_BYTE);
3447
        goto do_jcc;
3448
    case 0x180 ... 0x18f: /* jcc Jv */
3449
        if (dflag) {
3450
            val = insn_get(s, OT_LONG);
3451
        } else {
3452
            val = (int16_t)insn_get(s, OT_WORD); 
3453
        }
3454
    do_jcc:
3455
        next_eip = s->pc - s->cs_base;
3456
        val += next_eip;
3457
        if (s->dflag == 0)
3458
            val &= 0xffff;
3459
        gen_jcc(s, b, val, next_eip);
3460
        break;
3461

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

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

    
4024
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
4025
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
4026

    
4027
/* flags read by an operation */
4028
static uint16_t opc_read_flags[NB_OPS] = { 
4029
    [INDEX_op_aas] = CC_A,
4030
    [INDEX_op_aaa] = CC_A,
4031
    [INDEX_op_das] = CC_A | CC_C,
4032
    [INDEX_op_daa] = CC_A | CC_C,
4033

    
4034
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
4035
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
4036
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
4037
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
4038
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
4039
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
4040

    
4041
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
4042
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
4043
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
4044
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
4045
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
4046
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
4047

    
4048
    /* subtle: due to the incl/decl implementation, C is used */
4049
    [INDEX_op_update_inc_cc] = CC_C, 
4050

    
4051
    [INDEX_op_into] = CC_O,
4052

    
4053
    [INDEX_op_jb_subb] = CC_C,
4054
    [INDEX_op_jb_subw] = CC_C,
4055
    [INDEX_op_jb_subl] = CC_C,
4056

    
4057
    [INDEX_op_jz_subb] = CC_Z,
4058
    [INDEX_op_jz_subw] = CC_Z,
4059
    [INDEX_op_jz_subl] = CC_Z,
4060

    
4061
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
4062
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
4063
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
4064

    
4065
    [INDEX_op_js_subb] = CC_S,
4066
    [INDEX_op_js_subw] = CC_S,
4067
    [INDEX_op_js_subl] = CC_S,
4068

    
4069
    [INDEX_op_jl_subb] = CC_O | CC_S,
4070
    [INDEX_op_jl_subw] = CC_O | CC_S,
4071
    [INDEX_op_jl_subl] = CC_O | CC_S,
4072

    
4073
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
4074
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
4075
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
4076

    
4077
    [INDEX_op_loopnzw] = CC_Z,
4078
    [INDEX_op_loopnzl] = CC_Z,
4079
    [INDEX_op_loopzw] = CC_Z,
4080
    [INDEX_op_loopzl] = CC_Z,
4081

    
4082
    [INDEX_op_seto_T0_cc] = CC_O,
4083
    [INDEX_op_setb_T0_cc] = CC_C,
4084
    [INDEX_op_setz_T0_cc] = CC_Z,
4085
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
4086
    [INDEX_op_sets_T0_cc] = CC_S,
4087
    [INDEX_op_setp_T0_cc] = CC_P,
4088
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
4089
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
4090

    
4091
    [INDEX_op_setb_T0_subb] = CC_C,
4092
    [INDEX_op_setb_T0_subw] = CC_C,
4093
    [INDEX_op_setb_T0_subl] = CC_C,
4094

    
4095
    [INDEX_op_setz_T0_subb] = CC_Z,
4096
    [INDEX_op_setz_T0_subw] = CC_Z,
4097
    [INDEX_op_setz_T0_subl] = CC_Z,
4098

    
4099
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
4100
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
4101
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
4102

    
4103
    [INDEX_op_sets_T0_subb] = CC_S,
4104
    [INDEX_op_sets_T0_subw] = CC_S,
4105
    [INDEX_op_sets_T0_subl] = CC_S,
4106

    
4107
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
4108
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
4109
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
4110

    
4111
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
4112
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
4113
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
4114

    
4115
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
4116
    [INDEX_op_cmc] = CC_C,
4117
    [INDEX_op_salc] = CC_C,
4118

    
4119
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
4120
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
4121
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
4122
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
4123
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
4124
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
4125

    
4126
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
4127
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
4128
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
4129
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
4130
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
4131
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
4132
};
4133

    
4134
/* flags written by an operation */
4135
static uint16_t opc_write_flags[NB_OPS] = { 
4136
    [INDEX_op_update2_cc] = CC_OSZAPC,
4137
    [INDEX_op_update1_cc] = CC_OSZAPC,
4138
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
4139
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
4140
    /* subtle: due to the incl/decl implementation, C is used */
4141
    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
4142
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
4143

    
4144
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
4145
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
4146
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
4147
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
4148
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
4149
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
4150

    
4151
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
4152
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
4153
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
4154
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
4155
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
4156
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
4157

    
4158
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
4159
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
4160
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
4161
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
4162
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
4163
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
4164
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
4165
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
4166
    
4167
    /* bcd */
4168
    [INDEX_op_aam] = CC_OSZAPC,
4169
    [INDEX_op_aad] = CC_OSZAPC,
4170
    [INDEX_op_aas] = CC_OSZAPC,
4171
    [INDEX_op_aaa] = CC_OSZAPC,
4172
    [INDEX_op_das] = CC_OSZAPC,
4173
    [INDEX_op_daa] = CC_OSZAPC,
4174

    
4175
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
4176
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
4177
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4178
    [INDEX_op_clc] = CC_C,
4179
    [INDEX_op_stc] = CC_C,
4180
    [INDEX_op_cmc] = CC_C,
4181

    
4182
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
4183
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
4184
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
4185
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
4186
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
4187
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
4188

    
4189
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
4190
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
4191
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
4192
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
4193
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
4194
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
4195

    
4196
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
4197
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
4198
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
4199

    
4200
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
4201
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
4202
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
4203

    
4204
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
4205
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
4206
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
4207

    
4208
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
4209
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
4210
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
4211
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
4212

    
4213
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
4214
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
4215
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
4216
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
4217

    
4218
    [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
4219
    [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
4220
    [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
4221
    [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
4222
    [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
4223
    [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
4224

    
4225
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
4226
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
4227
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
4228
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
4229
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
4230
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
4231

    
4232
    [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
4233
    [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
4234
    [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
4235

    
4236
    [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
4237
    [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
4238
    [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
4239

    
4240
    [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
4241
    [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
4242
    [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
4243

    
4244
    [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4245
    [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4246
    [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
4247
    [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
4248

    
4249
    [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4250
    [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
4251
    [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
4252
    [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
4253

    
4254
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
4255
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
4256
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
4257
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
4258
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
4259
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
4260
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
4261
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
4262

    
4263
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
4264
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
4265
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4266
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4267

    
4268
#undef STRINGOP
4269
#define STRINGOP(x) \
4270
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
4271
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
4272
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
4273
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
4274
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
4275
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
4276
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
4277
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
4278
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
4279

    
4280
    STRINGOP(repz_scas)
4281
    STRINGOP(repnz_scas)
4282
    STRINGOP(repz_cmps)
4283
    STRINGOP(repnz_cmps)
4284

    
4285
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4286
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4287
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4288

    
4289
    [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4290
    [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4291
    [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4292

    
4293
    [INDEX_op_cmpxchg8b] = CC_Z,
4294
    [INDEX_op_lar] = CC_Z,
4295
    [INDEX_op_lsl] = CC_Z,
4296
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4297
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4298
};
4299

    
4300
/* simpler form of an operation if no flags need to be generated */
4301
static uint16_t opc_simpler[NB_OPS] = { 
4302
    [INDEX_op_update2_cc] = INDEX_op_nop,
4303
    [INDEX_op_update1_cc] = INDEX_op_nop,
4304
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
4305
#if 0
4306
    /* broken: CC_OP logic must be rewritten */
4307
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
4308
#endif
4309
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
4310
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
4311
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
4312

    
4313
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
4314
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
4315
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
4316

    
4317
    [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
4318
    [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
4319
    [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
4320

    
4321
    [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
4322
    [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
4323
    [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
4324

    
4325
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4326
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4327
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4328

    
4329
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4330
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4331
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4332

    
4333
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4334
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4335
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4336
};
4337

    
4338
void optimize_flags_init(void)
4339
{
4340
    int i;
4341
    /* put default values in arrays */
4342
    for(i = 0; i < NB_OPS; i++) {
4343
        if (opc_simpler[i] == 0)
4344
            opc_simpler[i] = i;
4345
    }
4346
}
4347

    
4348
/* CPU flags computation optimization: we move backward thru the
4349
   generated code to see which flags are needed. The operation is
4350
   modified if suitable */
4351
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4352
{
4353
    uint16_t *opc_ptr;
4354
    int live_flags, write_flags, op;
4355

    
4356
    opc_ptr = opc_buf + opc_buf_len;
4357
    /* live_flags contains the flags needed by the next instructions
4358
       in the code. At the end of the bloc, we consider that all the
4359
       flags are live. */
4360
    live_flags = CC_OSZAPC;
4361
    while (opc_ptr > opc_buf) {
4362
        op = *--opc_ptr;
4363
        /* if none of the flags written by the instruction is used,
4364
           then we can try to find a simpler instruction */
4365
        write_flags = opc_write_flags[op];
4366
        if ((live_flags & write_flags) == 0) {
4367
            *opc_ptr = opc_simpler[op];
4368
        }
4369
        /* compute the live flags before the instruction */
4370
        live_flags &= ~write_flags;
4371
        live_flags |= opc_read_flags[op];
4372
    }
4373
}
4374

    
4375
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4376
   basic block 'tb'. If search_pc is TRUE, also generate PC
4377
   information for each intermediate instruction. */
4378
static inline int gen_intermediate_code_internal(CPUState *env,
4379
                                                 TranslationBlock *tb, 
4380
                                                 int search_pc)
4381
{
4382
    DisasContext dc1, *dc = &dc1;
4383
    uint8_t *pc_ptr;
4384
    uint16_t *gen_opc_end;
4385
    int flags, j, lj;
4386
    long ret;
4387
    uint8_t *pc_start;
4388
    uint8_t *cs_base;
4389
    
4390
    /* generate intermediate code */
4391
    pc_start = (uint8_t *)tb->pc;
4392
    cs_base = (uint8_t *)tb->cs_base;
4393
    flags = tb->flags;
4394
       
4395
    dc->pe = env->cr[0] & CR0_PE_MASK;
4396
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
4397
    dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
4398
    dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
4399
    dc->f_st = 0;
4400
    dc->vm86 = (flags >> VM_SHIFT) & 1;
4401
    dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
4402
    dc->iopl = (flags >> IOPL_SHIFT) & 3;
4403
    dc->tf = (flags >> TF_SHIFT) & 1;
4404
    dc->cc_op = CC_OP_DYNAMIC;
4405
    dc->cs_base = cs_base;
4406
    dc->tb = tb;
4407
    dc->popl_esp_hack = 0;
4408
    /* select memory access functions */
4409
    dc->mem_index = 0;
4410
    if (flags & HF_SOFTMMU_MASK) {
4411
        if (dc->cpl == 3)
4412
            dc->mem_index = 6;
4413
        else
4414
            dc->mem_index = 3;
4415
    }
4416

    
4417
    gen_opc_ptr = gen_opc_buf;
4418
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4419
    gen_opparam_ptr = gen_opparam_buf;
4420

    
4421
    dc->is_jmp = DISAS_NEXT;
4422
    pc_ptr = pc_start;
4423
    lj = -1;
4424

    
4425
    /* if irq were inhibited for the next instruction, we can disable
4426
       them here as it is simpler (otherwise jumps would have to
4427
       handled as special case) */
4428
    if (flags & HF_INHIBIT_IRQ_MASK) {
4429
        gen_op_reset_inhibit_irq();
4430
    }
4431
    do {
4432
        if (env->nb_breakpoints > 0) {
4433
            for(j = 0; j < env->nb_breakpoints; j++) {
4434
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4435
                    gen_debug(dc, pc_ptr - dc->cs_base);
4436
                    goto the_end;
4437
                }
4438
            }
4439
        }
4440
        if (search_pc) {
4441
            j = gen_opc_ptr - gen_opc_buf;
4442
            if (lj < j) {
4443
                lj++;
4444
                while (lj < j)
4445
                    gen_opc_instr_start[lj++] = 0;
4446
            }
4447
            gen_opc_pc[lj] = (uint32_t)pc_ptr;
4448
            gen_opc_cc_op[lj] = dc->cc_op;
4449
            gen_opc_instr_start[lj] = 1;
4450
        }
4451
        ret = disas_insn(dc, pc_ptr);
4452
        if (ret == -1) {
4453
            /* we trigger an illegal instruction operation only if it
4454
               is the first instruction. Otherwise, we simply stop
4455
               generating the code just before it */
4456
            if (pc_ptr == pc_start)
4457
                return -1;
4458
            else
4459
                break;
4460
        }
4461
        pc_ptr = (void *)ret;
4462
        /* if single step mode, we generate only one instruction and
4463
           generate an exception */
4464
        if (dc->tf)
4465
            break;
4466
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
4467
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4468
    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4469
        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4470
    }
4471

    
4472
    /* we must store the eflags state if it is not already done */
4473
    if (dc->is_jmp != DISAS_TB_JUMP) {
4474
        if (dc->cc_op != CC_OP_DYNAMIC)
4475
            gen_op_set_cc_op(dc->cc_op);
4476
        if (dc->is_jmp != DISAS_JUMP) {
4477
            /* we add an additionnal jmp to update the simulated PC */
4478
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4479
        }
4480
    }
4481
    if (dc->tf) {
4482
        gen_op_raise_exception(EXCP01_SSTP);
4483
    }
4484
 the_end:
4485
    if (dc->is_jmp != DISAS_TB_JUMP) {
4486
        /* indicate that the hash table must be used to find the next TB */
4487
        gen_op_movl_T0_0();
4488
        gen_op_exit_tb();
4489
    }
4490
    *gen_opc_ptr = INDEX_op_end;
4491
    /* we don't forget to fill the last values */
4492
    if (search_pc) {
4493
        j = gen_opc_ptr - gen_opc_buf;
4494
        lj++;
4495
        while (lj <= j)
4496
            gen_opc_instr_start[lj++] = 0;
4497
    }
4498
        
4499
#ifdef DEBUG_DISAS
4500
    if (loglevel) {
4501
        fprintf(logfile, "----------------\n");
4502
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4503
        disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4504
        fprintf(logfile, "\n");
4505

    
4506
        fprintf(logfile, "OP:\n");
4507
        dump_ops(gen_opc_buf, gen_opparam_buf);
4508
        fprintf(logfile, "\n");
4509
    }
4510
#endif
4511

    
4512
    /* optimize flag computations */
4513
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4514

    
4515
#ifdef DEBUG_DISAS
4516
    if (loglevel) {
4517
        fprintf(logfile, "AFTER FLAGS OPT:\n");
4518
        dump_ops(gen_opc_buf, gen_opparam_buf);
4519
        fprintf(logfile, "\n");
4520
    }
4521
#endif
4522
    if (!search_pc)
4523
        tb->size = pc_ptr - pc_start;
4524
    return 0;
4525
}
4526

    
4527
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4528
{
4529
    return gen_intermediate_code_internal(env, tb, 0);
4530
}
4531

    
4532
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4533
{
4534
    return gen_intermediate_code_internal(env, tb, 1);
4535
}
4536