Statistics
| Branch: | Revision:

root / translate-i386.c @ a412ac57

History | View | Annotate | Download (127.7 kB)

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

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

    
33
//#define DEBUG_MMU
34

    
35
/* XXX: move that elsewhere */
36
static uint16_t *gen_opc_ptr;
37
static uint32_t *gen_opparam_ptr;
38

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
568
static GenOpFunc *gen_op_lds_T0_A0[3] = {
569
    gen_op_ldsb_T0_A0,
570
    gen_op_ldsw_T0_A0,
571
};
572

    
573
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
574
    gen_op_ldub_T0_A0,
575
    gen_op_lduw_T0_A0,
576
};
577

    
578
/* sign does not matter */
579
static GenOpFunc *gen_op_ld_T0_A0[3] = {
580
    gen_op_ldub_T0_A0,
581
    gen_op_lduw_T0_A0,
582
    gen_op_ldl_T0_A0,
583
};
584

    
585
static GenOpFunc *gen_op_ld_T1_A0[3] = {
586
    gen_op_ldub_T1_A0,
587
    gen_op_lduw_T1_A0,
588
    gen_op_ldl_T1_A0,
589
};
590

    
591
static GenOpFunc *gen_op_st_T0_A0[3] = {
592
    gen_op_stb_T0_A0,
593
    gen_op_stw_T0_A0,
594
    gen_op_stl_T0_A0,
595
};
596

    
597
/* the _a32 and _a16 string operations use A0 as the base register. */
598

    
599
#define STRINGOP(x) \
600
    gen_op_ ## x ## b_fast, \
601
    gen_op_ ## x ## w_fast, \
602
    gen_op_ ## x ## l_fast, \
603
    gen_op_ ## x ## b_a32, \
604
    gen_op_ ## x ## w_a32, \
605
    gen_op_ ## x ## l_a32, \
606
    gen_op_ ## x ## b_a16, \
607
    gen_op_ ## x ## w_a16, \
608
    gen_op_ ## x ## l_a16,
609
     
610
static GenOpFunc *gen_op_movs[9 * 2] = {
611
    STRINGOP(movs)
612
    STRINGOP(rep_movs)
613
};
614

    
615
static GenOpFunc *gen_op_stos[9 * 2] = {
616
    STRINGOP(stos)
617
    STRINGOP(rep_stos)
618
};
619

    
620
static GenOpFunc *gen_op_lods[9 * 2] = {
621
    STRINGOP(lods)
622
    STRINGOP(rep_lods)
623
};
624

    
625
static GenOpFunc *gen_op_scas[9 * 3] = {
626
    STRINGOP(scas)
627
    STRINGOP(repz_scas)
628
    STRINGOP(repnz_scas)
629
};
630

    
631
static GenOpFunc *gen_op_cmps[9 * 3] = {
632
    STRINGOP(cmps)
633
    STRINGOP(repz_cmps)
634
    STRINGOP(repnz_cmps)
635
};
636

    
637
static GenOpFunc *gen_op_ins[9 * 2] = {
638
    STRINGOP(ins)
639
    STRINGOP(rep_ins)
640
};
641

    
642

    
643
static GenOpFunc *gen_op_outs[9 * 2] = {
644
    STRINGOP(outs)
645
    STRINGOP(rep_outs)
646
};
647

    
648

    
649
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
650
{
651
    int index, override;
652

    
653
    override = s->override;
654
    if (s->aflag) {
655
        /* 32 bit address */
656
        if (s->addseg && override < 0)
657
            override = R_DS;
658
        if (override >= 0) {
659
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
660
            index = 3 + ot;
661
        } else {
662
            index = ot;
663
        }
664
    } else {
665
        if (override < 0)
666
            override = R_DS;
667
        gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
668
        /* 16 address, always override */
669
        index = 6 + ot;
670
    }
671
    func[index]();
672
}
673

    
674
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
675
{
676
    int index;
677
            
678
    if (s->aflag) {
679
        if (s->addseg) {
680
            index = 3 + ot;
681
        } else {
682
            index = ot;
683
        }
684
    } else {
685
        index = 6 + ot;
686
    }
687
    func[index]();
688
}
689

    
690

    
691
static GenOpFunc *gen_op_in[3] = {
692
    gen_op_inb_T0_T1,
693
    gen_op_inw_T0_T1,
694
    gen_op_inl_T0_T1,
695
};
696

    
697
static GenOpFunc *gen_op_out[3] = {
698
    gen_op_outb_T0_T1,
699
    gen_op_outw_T0_T1,
700
    gen_op_outl_T0_T1,
701
};
702

    
703
enum {
704
    JCC_O,
705
    JCC_B,
706
    JCC_Z,
707
    JCC_BE,
708
    JCC_S,
709
    JCC_P,
710
    JCC_L,
711
    JCC_LE,
712
};
713

    
714
static GenOpFunc3 *gen_jcc_sub[3][8] = {
715
    [OT_BYTE] = {
716
        NULL,
717
        gen_op_jb_subb,
718
        gen_op_jz_subb,
719
        gen_op_jbe_subb,
720
        gen_op_js_subb,
721
        NULL,
722
        gen_op_jl_subb,
723
        gen_op_jle_subb,
724
    },
725
    [OT_WORD] = {
726
        NULL,
727
        gen_op_jb_subw,
728
        gen_op_jz_subw,
729
        gen_op_jbe_subw,
730
        gen_op_js_subw,
731
        NULL,
732
        gen_op_jl_subw,
733
        gen_op_jle_subw,
734
    },
735
    [OT_LONG] = {
736
        NULL,
737
        gen_op_jb_subl,
738
        gen_op_jz_subl,
739
        gen_op_jbe_subl,
740
        gen_op_js_subl,
741
        NULL,
742
        gen_op_jl_subl,
743
        gen_op_jle_subl,
744
    },
745
};
746
static GenOpFunc2 *gen_op_loop[2][4] = {
747
    [0] = {
748
        gen_op_loopnzw,
749
        gen_op_loopzw,
750
        gen_op_loopw,
751
        gen_op_jecxzw,
752
    },
753
    [1] = {
754
        gen_op_loopnzl,
755
        gen_op_loopzl,
756
        gen_op_loopl,
757
        gen_op_jecxzl,
758
    },
759
};
760

    
761
static GenOpFunc *gen_setcc_slow[8] = {
762
    gen_op_seto_T0_cc,
763
    gen_op_setb_T0_cc,
764
    gen_op_setz_T0_cc,
765
    gen_op_setbe_T0_cc,
766
    gen_op_sets_T0_cc,
767
    gen_op_setp_T0_cc,
768
    gen_op_setl_T0_cc,
769
    gen_op_setle_T0_cc,
770
};
771

    
772
static GenOpFunc *gen_setcc_sub[3][8] = {
773
    [OT_BYTE] = {
774
        NULL,
775
        gen_op_setb_T0_subb,
776
        gen_op_setz_T0_subb,
777
        gen_op_setbe_T0_subb,
778
        gen_op_sets_T0_subb,
779
        NULL,
780
        gen_op_setl_T0_subb,
781
        gen_op_setle_T0_subb,
782
    },
783
    [OT_WORD] = {
784
        NULL,
785
        gen_op_setb_T0_subw,
786
        gen_op_setz_T0_subw,
787
        gen_op_setbe_T0_subw,
788
        gen_op_sets_T0_subw,
789
        NULL,
790
        gen_op_setl_T0_subw,
791
        gen_op_setle_T0_subw,
792
    },
793
    [OT_LONG] = {
794
        NULL,
795
        gen_op_setb_T0_subl,
796
        gen_op_setz_T0_subl,
797
        gen_op_setbe_T0_subl,
798
        gen_op_sets_T0_subl,
799
        NULL,
800
        gen_op_setl_T0_subl,
801
        gen_op_setle_T0_subl,
802
    },
803
};
804

    
805
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
806
    gen_op_fadd_ST0_FT0,
807
    gen_op_fmul_ST0_FT0,
808
    gen_op_fcom_ST0_FT0,
809
    gen_op_fcom_ST0_FT0,
810
    gen_op_fsub_ST0_FT0,
811
    gen_op_fsubr_ST0_FT0,
812
    gen_op_fdiv_ST0_FT0,
813
    gen_op_fdivr_ST0_FT0,
814
};
815

    
816
/* NOTE the exception in "r" op ordering */
817
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
818
    gen_op_fadd_STN_ST0,
819
    gen_op_fmul_STN_ST0,
820
    NULL,
821
    NULL,
822
    gen_op_fsubr_STN_ST0,
823
    gen_op_fsub_STN_ST0,
824
    gen_op_fdivr_STN_ST0,
825
    gen_op_fdiv_STN_ST0,
826
};
827

    
828
/* if d == OR_TMP0, it means memory operand (address in A0) */
829
static void gen_op(DisasContext *s1, int op, int ot, int d)
830
{
831
    GenOpFunc *gen_update_cc;
832
    
833
    if (d != OR_TMP0) {
834
        gen_op_mov_TN_reg[ot][0][d]();
835
    } else {
836
        gen_op_ld_T0_A0[ot]();
837
    }
838
    switch(op) {
839
    case OP_ADCL:
840
    case OP_SBBL:
841
        if (s1->cc_op != CC_OP_DYNAMIC)
842
            gen_op_set_cc_op(s1->cc_op);
843
        if (d != OR_TMP0) {
844
            gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
845
            gen_op_mov_reg_T0[ot][d]();
846
        } else {
847
            gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL]();
848
        }
849
        s1->cc_op = CC_OP_DYNAMIC;
850
        goto the_end;
851
    case OP_ADDL:
852
        gen_op_addl_T0_T1();
853
        s1->cc_op = CC_OP_ADDB + ot;
854
        gen_update_cc = gen_op_update2_cc;
855
        break;
856
    case OP_SUBL:
857
        gen_op_subl_T0_T1();
858
        s1->cc_op = CC_OP_SUBB + ot;
859
        gen_update_cc = gen_op_update2_cc;
860
        break;
861
    default:
862
    case OP_ANDL:
863
    case OP_ORL:
864
    case OP_XORL:
865
        gen_op_arith_T0_T1_cc[op]();
866
        s1->cc_op = CC_OP_LOGICB + ot;
867
        gen_update_cc = gen_op_update1_cc;
868
        break;
869
    case OP_CMPL:
870
        gen_op_cmpl_T0_T1_cc();
871
        s1->cc_op = CC_OP_SUBB + ot;
872
        gen_update_cc = NULL;
873
        break;
874
    }
875
    if (op != OP_CMPL) {
876
        if (d != OR_TMP0)
877
            gen_op_mov_reg_T0[ot][d]();
878
        else
879
            gen_op_st_T0_A0[ot]();
880
    }
881
    /* the flags update must happen after the memory write (precise
882
       exception support) */
883
    if (gen_update_cc)
884
        gen_update_cc();
885
 the_end: ;
886
}
887

    
888
/* if d == OR_TMP0, it means memory operand (address in A0) */
889
static void gen_inc(DisasContext *s1, int ot, int d, int c)
890
{
891
    if (d != OR_TMP0)
892
        gen_op_mov_TN_reg[ot][0][d]();
893
    else
894
        gen_op_ld_T0_A0[ot]();
895
    if (s1->cc_op != CC_OP_DYNAMIC)
896
        gen_op_set_cc_op(s1->cc_op);
897
    if (c > 0) {
898
        gen_op_incl_T0();
899
        s1->cc_op = CC_OP_INCB + ot;
900
    } else {
901
        gen_op_decl_T0();
902
        s1->cc_op = CC_OP_DECB + ot;
903
    }
904
    if (d != OR_TMP0)
905
        gen_op_mov_reg_T0[ot][d]();
906
    else
907
        gen_op_st_T0_A0[ot]();
908
    gen_op_update_inc_cc();
909
}
910

    
911
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
912
{
913
    if (d != OR_TMP0)
914
        gen_op_mov_TN_reg[ot][0][d]();
915
    else
916
        gen_op_ld_T0_A0[ot]();
917
    if (s != OR_TMP1)
918
        gen_op_mov_TN_reg[ot][1][s]();
919
    /* for zero counts, flags are not updated, so must do it dynamically */
920
    if (s1->cc_op != CC_OP_DYNAMIC)
921
        gen_op_set_cc_op(s1->cc_op);
922
    
923
    if (d != OR_TMP0)
924
        gen_op_shift_T0_T1_cc[ot][op]();
925
    else
926
        gen_op_shift_mem_T0_T1_cc[ot][op]();
927
    if (d != OR_TMP0)
928
        gen_op_mov_reg_T0[ot][d]();
929
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
930
}
931

    
932
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
933
{
934
    /* currently not optimized */
935
    gen_op_movl_T1_im(c);
936
    gen_shift(s1, op, ot, d, OR_TMP1);
937
}
938

    
939
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
940
{
941
    int havesib;
942
    int base, disp;
943
    int index;
944
    int scale;
945
    int opreg;
946
    int mod, rm, code, override, must_add_seg;
947

    
948
    override = s->override;
949
    must_add_seg = s->addseg;
950
    if (override >= 0)
951
        must_add_seg = 1;
952
    mod = (modrm >> 6) & 3;
953
    rm = modrm & 7;
954

    
955
    if (s->aflag) {
956

    
957
        havesib = 0;
958
        base = rm;
959
        index = 0;
960
        scale = 0;
961
        
962
        if (base == 4) {
963
            havesib = 1;
964
            code = ldub(s->pc++);
965
            scale = (code >> 6) & 3;
966
            index = (code >> 3) & 7;
967
            base = code & 7;
968
        }
969

    
970
        switch (mod) {
971
        case 0:
972
            if (base == 5) {
973
                base = -1;
974
                disp = ldl(s->pc);
975
                s->pc += 4;
976
            } else {
977
                disp = 0;
978
            }
979
            break;
980
        case 1:
981
            disp = (int8_t)ldub(s->pc++);
982
            break;
983
        default:
984
        case 2:
985
            disp = ldl(s->pc);
986
            s->pc += 4;
987
            break;
988
        }
989
        
990
        if (base >= 0) {
991
            /* for correct popl handling with esp */
992
            if (base == 4 && s->popl_esp_hack)
993
                disp += s->popl_esp_hack;
994
            gen_op_movl_A0_reg[base]();
995
            if (disp != 0)
996
                gen_op_addl_A0_im(disp);
997
        } else {
998
            gen_op_movl_A0_im(disp);
999
        }
1000
        /* XXX: index == 4 is always invalid */
1001
        if (havesib && (index != 4 || scale != 0)) {
1002
            gen_op_addl_A0_reg_sN[scale][index]();
1003
        }
1004
        if (must_add_seg) {
1005
            if (override < 0) {
1006
                if (base == R_EBP || base == R_ESP)
1007
                    override = R_SS;
1008
                else
1009
                    override = R_DS;
1010
            }
1011
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1012
        }
1013
    } else {
1014
        switch (mod) {
1015
        case 0:
1016
            if (rm == 6) {
1017
                disp = lduw(s->pc);
1018
                s->pc += 2;
1019
                gen_op_movl_A0_im(disp);
1020
                rm = 0; /* avoid SS override */
1021
                goto no_rm;
1022
            } else {
1023
                disp = 0;
1024
            }
1025
            break;
1026
        case 1:
1027
            disp = (int8_t)ldub(s->pc++);
1028
            break;
1029
        default:
1030
        case 2:
1031
            disp = lduw(s->pc);
1032
            s->pc += 2;
1033
            break;
1034
        }
1035
        switch(rm) {
1036
        case 0:
1037
            gen_op_movl_A0_reg[R_EBX]();
1038
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1039
            break;
1040
        case 1:
1041
            gen_op_movl_A0_reg[R_EBX]();
1042
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1043
            break;
1044
        case 2:
1045
            gen_op_movl_A0_reg[R_EBP]();
1046
            gen_op_addl_A0_reg_sN[0][R_ESI]();
1047
            break;
1048
        case 3:
1049
            gen_op_movl_A0_reg[R_EBP]();
1050
            gen_op_addl_A0_reg_sN[0][R_EDI]();
1051
            break;
1052
        case 4:
1053
            gen_op_movl_A0_reg[R_ESI]();
1054
            break;
1055
        case 5:
1056
            gen_op_movl_A0_reg[R_EDI]();
1057
            break;
1058
        case 6:
1059
            gen_op_movl_A0_reg[R_EBP]();
1060
            break;
1061
        default:
1062
        case 7:
1063
            gen_op_movl_A0_reg[R_EBX]();
1064
            break;
1065
        }
1066
        if (disp != 0)
1067
            gen_op_addl_A0_im(disp);
1068
        gen_op_andl_A0_ffff();
1069
    no_rm:
1070
        if (must_add_seg) {
1071
            if (override < 0) {
1072
                if (rm == 2 || rm == 3 || rm == 6)
1073
                    override = R_SS;
1074
                else
1075
                    override = R_DS;
1076
            }
1077
            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1078
        }
1079
    }
1080

    
1081
    opreg = OR_A0;
1082
    disp = 0;
1083
    *reg_ptr = opreg;
1084
    *offset_ptr = disp;
1085
}
1086

    
1087
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1088
   OR_TMP0 */
1089
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1090
{
1091
    int mod, rm, opreg, disp;
1092

    
1093
    mod = (modrm >> 6) & 3;
1094
    rm = modrm & 7;
1095
    if (mod == 3) {
1096
        if (is_store) {
1097
            if (reg != OR_TMP0)
1098
                gen_op_mov_TN_reg[ot][0][reg]();
1099
            gen_op_mov_reg_T0[ot][rm]();
1100
        } else {
1101
            gen_op_mov_TN_reg[ot][0][rm]();
1102
            if (reg != OR_TMP0)
1103
                gen_op_mov_reg_T0[ot][reg]();
1104
        }
1105
    } else {
1106
        gen_lea_modrm(s, modrm, &opreg, &disp);
1107
        if (is_store) {
1108
            if (reg != OR_TMP0)
1109
                gen_op_mov_TN_reg[ot][0][reg]();
1110
            gen_op_st_T0_A0[ot]();
1111
        } else {
1112
            gen_op_ld_T0_A0[ot]();
1113
            if (reg != OR_TMP0)
1114
                gen_op_mov_reg_T0[ot][reg]();
1115
        }
1116
    }
1117
}
1118

    
1119
static inline uint32_t insn_get(DisasContext *s, int ot)
1120
{
1121
    uint32_t ret;
1122

    
1123
    switch(ot) {
1124
    case OT_BYTE:
1125
        ret = ldub(s->pc);
1126
        s->pc++;
1127
        break;
1128
    case OT_WORD:
1129
        ret = lduw(s->pc);
1130
        s->pc += 2;
1131
        break;
1132
    default:
1133
    case OT_LONG:
1134
        ret = ldl(s->pc);
1135
        s->pc += 4;
1136
        break;
1137
    }
1138
    return ret;
1139
}
1140

    
1141
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1142
{
1143
    TranslationBlock *tb;
1144
    int inv, jcc_op;
1145
    GenOpFunc3 *func;
1146

    
1147
    inv = b & 1;
1148
    jcc_op = (b >> 1) & 7;
1149
    switch(s->cc_op) {
1150
        /* we optimize the cmp/jcc case */
1151
    case CC_OP_SUBB:
1152
    case CC_OP_SUBW:
1153
    case CC_OP_SUBL:
1154
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1155
        break;
1156
        
1157
        /* some jumps are easy to compute */
1158
    case CC_OP_ADDB:
1159
    case CC_OP_ADDW:
1160
    case CC_OP_ADDL:
1161
    case CC_OP_ADCB:
1162
    case CC_OP_ADCW:
1163
    case CC_OP_ADCL:
1164
    case CC_OP_SBBB:
1165
    case CC_OP_SBBW:
1166
    case CC_OP_SBBL:
1167
    case CC_OP_LOGICB:
1168
    case CC_OP_LOGICW:
1169
    case CC_OP_LOGICL:
1170
    case CC_OP_INCB:
1171
    case CC_OP_INCW:
1172
    case CC_OP_INCL:
1173
    case CC_OP_DECB:
1174
    case CC_OP_DECW:
1175
    case CC_OP_DECL:
1176
    case CC_OP_SHLB:
1177
    case CC_OP_SHLW:
1178
    case CC_OP_SHLL:
1179
    case CC_OP_SARB:
1180
    case CC_OP_SARW:
1181
    case CC_OP_SARL:
1182
        switch(jcc_op) {
1183
        case JCC_Z:
1184
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1185
            break;
1186
        case JCC_S:
1187
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1188
            break;
1189
        default:
1190
            func = NULL;
1191
            break;
1192
        }
1193
        break;
1194
    default:
1195
        func = NULL;
1196
        break;
1197
    }
1198

    
1199
    if (s->cc_op != CC_OP_DYNAMIC)
1200
        gen_op_set_cc_op(s->cc_op);
1201

    
1202
    if (!func) {
1203
        gen_setcc_slow[jcc_op]();
1204
        func = gen_op_jcc;
1205
    }
1206
    
1207
    tb = s->tb;
1208
    if (!inv) {
1209
        func((long)tb, val, next_eip);
1210
    } else {
1211
        func((long)tb, next_eip, val);
1212
    }
1213
    s->is_jmp = 3;
1214
}
1215

    
1216
static void gen_setcc(DisasContext *s, int b)
1217
{
1218
    int inv, jcc_op;
1219
    GenOpFunc *func;
1220

    
1221
    inv = b & 1;
1222
    jcc_op = (b >> 1) & 7;
1223
    switch(s->cc_op) {
1224
        /* we optimize the cmp/jcc case */
1225
    case CC_OP_SUBB:
1226
    case CC_OP_SUBW:
1227
    case CC_OP_SUBL:
1228
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1229
        if (!func)
1230
            goto slow_jcc;
1231
        break;
1232
        
1233
        /* some jumps are easy to compute */
1234
    case CC_OP_ADDB:
1235
    case CC_OP_ADDW:
1236
    case CC_OP_ADDL:
1237
    case CC_OP_LOGICB:
1238
    case CC_OP_LOGICW:
1239
    case CC_OP_LOGICL:
1240
    case CC_OP_INCB:
1241
    case CC_OP_INCW:
1242
    case CC_OP_INCL:
1243
    case CC_OP_DECB:
1244
    case CC_OP_DECW:
1245
    case CC_OP_DECL:
1246
    case CC_OP_SHLB:
1247
    case CC_OP_SHLW:
1248
    case CC_OP_SHLL:
1249
        switch(jcc_op) {
1250
        case JCC_Z:
1251
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1252
            break;
1253
        case JCC_S:
1254
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1255
            break;
1256
        default:
1257
            goto slow_jcc;
1258
        }
1259
        break;
1260
    default:
1261
    slow_jcc:
1262
        if (s->cc_op != CC_OP_DYNAMIC)
1263
            gen_op_set_cc_op(s->cc_op);
1264
        func = gen_setcc_slow[jcc_op];
1265
        break;
1266
    }
1267
    func();
1268
    if (inv) {
1269
        gen_op_xor_T0_1();
1270
    }
1271
}
1272

    
1273
/* move T0 to seg_reg and compute if the CPU state may change */
1274
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1275
{
1276
    if (s->pe && !s->vm86)
1277
        gen_op_movl_seg_T0(seg_reg, cur_eip);
1278
    else
1279
        gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1280
    if (!s->addseg && seg_reg < R_FS)
1281
        s->is_jmp = 2; /* abort translation because the register may
1282
                          have a non zero base */
1283
}
1284

    
1285
/* generate a push. It depends on ss32, addseg and dflag */
1286
static void gen_push_T0(DisasContext *s)
1287
{
1288
    if (s->ss32) {
1289
        if (!s->addseg) {
1290
            if (s->dflag)
1291
                gen_op_pushl_T0();
1292
            else
1293
                gen_op_pushw_T0();
1294
        } else {
1295
            if (s->dflag)
1296
                gen_op_pushl_ss32_T0();
1297
            else
1298
                gen_op_pushw_ss32_T0();
1299
        }
1300
    } else {
1301
        if (s->dflag)
1302
            gen_op_pushl_ss16_T0();
1303
        else
1304
            gen_op_pushw_ss16_T0();
1305
    }
1306
}
1307

    
1308
/* two step pop is necessary for precise exceptions */
1309
static void gen_pop_T0(DisasContext *s)
1310
{
1311
    if (s->ss32) {
1312
        if (!s->addseg) {
1313
            if (s->dflag)
1314
                gen_op_popl_T0();
1315
            else
1316
                gen_op_popw_T0();
1317
        } else {
1318
            if (s->dflag)
1319
                gen_op_popl_ss32_T0();
1320
            else
1321
                gen_op_popw_ss32_T0();
1322
        }
1323
    } else {
1324
        if (s->dflag)
1325
            gen_op_popl_ss16_T0();
1326
        else
1327
            gen_op_popw_ss16_T0();
1328
    }
1329
}
1330

    
1331
static inline void gen_stack_update(DisasContext *s, int addend)
1332
{
1333
    if (s->ss32) {
1334
        if (addend == 2)
1335
            gen_op_addl_ESP_2();
1336
        else if (addend == 4)
1337
            gen_op_addl_ESP_4();
1338
        else 
1339
            gen_op_addl_ESP_im(addend);
1340
    } else {
1341
        if (addend == 2)
1342
            gen_op_addw_ESP_2();
1343
        else if (addend == 4)
1344
            gen_op_addw_ESP_4();
1345
        else
1346
            gen_op_addw_ESP_im(addend);
1347
    }
1348
}
1349

    
1350
static void gen_pop_update(DisasContext *s)
1351
{
1352
    gen_stack_update(s, 2 << s->dflag);
1353
}
1354

    
1355
static void gen_stack_A0(DisasContext *s)
1356
{
1357
    gen_op_movl_A0_ESP();
1358
    if (!s->ss32)
1359
        gen_op_andl_A0_ffff();
1360
    gen_op_movl_T1_A0();
1361
    if (s->addseg)
1362
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1363
}
1364

    
1365
/* NOTE: wrap around in 16 bit not fully handled */
1366
static void gen_pusha(DisasContext *s)
1367
{
1368
    int i;
1369
    gen_op_movl_A0_ESP();
1370
    gen_op_addl_A0_im(-16 <<  s->dflag);
1371
    if (!s->ss32)
1372
        gen_op_andl_A0_ffff();
1373
    gen_op_movl_T1_A0();
1374
    if (s->addseg)
1375
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1376
    for(i = 0;i < 8; i++) {
1377
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1378
        gen_op_st_T0_A0[OT_WORD + s->dflag]();
1379
        gen_op_addl_A0_im(2 <<  s->dflag);
1380
    }
1381
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1382
}
1383

    
1384
/* NOTE: wrap around in 16 bit not fully handled */
1385
static void gen_popa(DisasContext *s)
1386
{
1387
    int i;
1388
    gen_op_movl_A0_ESP();
1389
    if (!s->ss32)
1390
        gen_op_andl_A0_ffff();
1391
    gen_op_movl_T1_A0();
1392
    gen_op_addl_T1_im(16 <<  s->dflag);
1393
    if (s->addseg)
1394
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1395
    for(i = 0;i < 8; i++) {
1396
        /* ESP is not reloaded */
1397
        if (i != 3) {
1398
            gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1399
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1400
        }
1401
        gen_op_addl_A0_im(2 <<  s->dflag);
1402
    }
1403
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1404
}
1405

    
1406
/* NOTE: wrap around in 16 bit not fully handled */
1407
/* XXX: check this */
1408
static void gen_enter(DisasContext *s, int esp_addend, int level)
1409
{
1410
    int ot, level1, addend, opsize;
1411

    
1412
    ot = s->dflag + OT_WORD;
1413
    level &= 0x1f;
1414
    level1 = level;
1415
    opsize = 2 << s->dflag;
1416

    
1417
    gen_op_movl_A0_ESP();
1418
    gen_op_addl_A0_im(-opsize);
1419
    if (!s->ss32)
1420
        gen_op_andl_A0_ffff();
1421
    gen_op_movl_T1_A0();
1422
    if (s->addseg)
1423
        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1424
    /* push bp */
1425
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1426
    gen_op_st_T0_A0[ot]();
1427
    if (level) {
1428
        while (level--) {
1429
            gen_op_addl_A0_im(-opsize);
1430
            gen_op_addl_T0_im(-opsize);
1431
            gen_op_st_T0_A0[ot]();
1432
        }
1433
        gen_op_addl_A0_im(-opsize);
1434
        /* XXX: add st_T1_A0 ? */
1435
        gen_op_movl_T0_T1();
1436
        gen_op_st_T0_A0[ot]();
1437
    }
1438
    gen_op_mov_reg_T1[ot][R_EBP]();
1439
    addend = -esp_addend;
1440
    if (level1)
1441
        addend -= opsize * (level1 + 1);
1442
    gen_op_addl_T1_im(addend);
1443
    gen_op_mov_reg_T1[ot][R_ESP]();
1444
}
1445

    
1446
static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1447
{
1448
    if (s->cc_op != CC_OP_DYNAMIC)
1449
        gen_op_set_cc_op(s->cc_op);
1450
    gen_op_jmp_im(cur_eip);
1451
    gen_op_raise_exception(trapno);
1452
    s->is_jmp = 1;
1453
}
1454

    
1455
/* an interrupt is different from an exception because of the
1456
   priviledge checks */
1457
static void gen_interrupt(DisasContext *s, int intno, 
1458
                          unsigned int cur_eip, unsigned int next_eip)
1459
{
1460
    if (s->cc_op != CC_OP_DYNAMIC)
1461
        gen_op_set_cc_op(s->cc_op);
1462
    gen_op_jmp_im(cur_eip);
1463
    gen_op_raise_interrupt(intno, next_eip);
1464
    s->is_jmp = 1;
1465
}
1466

    
1467
static void gen_debug(DisasContext *s, unsigned int cur_eip)
1468
{
1469
    if (s->cc_op != CC_OP_DYNAMIC)
1470
        gen_op_set_cc_op(s->cc_op);
1471
    gen_op_jmp_im(cur_eip);
1472
    gen_op_debug();
1473
    s->is_jmp = 1;
1474
}
1475

    
1476
/* generate a jump to eip. No segment change must happen before as a
1477
   direct call to the next block may occur */
1478
static void gen_jmp(DisasContext *s, unsigned int eip)
1479
{
1480
    TranslationBlock *tb = s->tb;
1481

    
1482
    if (s->cc_op != CC_OP_DYNAMIC)
1483
        gen_op_set_cc_op(s->cc_op);
1484
    gen_op_jmp_tb_next((long)tb, eip);
1485
    s->is_jmp = 3;
1486
}
1487

    
1488
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1489
   is set to true if the instruction sets the PC (last instruction of
1490
   a basic block) */
1491
long disas_insn(DisasContext *s, uint8_t *pc_start)
1492
{
1493
    int b, prefixes, aflag, dflag;
1494
    int shift, ot;
1495
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1496
    unsigned int next_eip;
1497

    
1498
    s->pc = pc_start;
1499
    prefixes = 0;
1500
    aflag = s->code32;
1501
    dflag = s->code32;
1502
    s->override = -1;
1503
 next_byte:
1504
    b = ldub(s->pc);
1505
    s->pc++;
1506
    /* check prefixes */
1507
    switch (b) {
1508
    case 0xf3:
1509
        prefixes |= PREFIX_REPZ;
1510
        goto next_byte;
1511
    case 0xf2:
1512
        prefixes |= PREFIX_REPNZ;
1513
        goto next_byte;
1514
    case 0xf0:
1515
        prefixes |= PREFIX_LOCK;
1516
        goto next_byte;
1517
    case 0x2e:
1518
        s->override = R_CS;
1519
        goto next_byte;
1520
    case 0x36:
1521
        s->override = R_SS;
1522
        goto next_byte;
1523
    case 0x3e:
1524
        s->override = R_DS;
1525
        goto next_byte;
1526
    case 0x26:
1527
        s->override = R_ES;
1528
        goto next_byte;
1529
    case 0x64:
1530
        s->override = R_FS;
1531
        goto next_byte;
1532
    case 0x65:
1533
        s->override = R_GS;
1534
        goto next_byte;
1535
    case 0x66:
1536
        prefixes |= PREFIX_DATA;
1537
        goto next_byte;
1538
    case 0x67:
1539
        prefixes |= PREFIX_ADR;
1540
        goto next_byte;
1541
    }
1542

    
1543
    if (prefixes & PREFIX_DATA)
1544
        dflag ^= 1;
1545
    if (prefixes & PREFIX_ADR)
1546
        aflag ^= 1;
1547

    
1548
    s->prefix = prefixes;
1549
    s->aflag = aflag;
1550
    s->dflag = dflag;
1551

    
1552
    /* lock generation */
1553
    if (prefixes & PREFIX_LOCK)
1554
        gen_op_lock();
1555

    
1556
    /* now check op code */
1557
 reswitch:
1558
    switch(b) {
1559
    case 0x0f:
1560
        /**************************/
1561
        /* extended op code */
1562
        b = ldub(s->pc++) | 0x100;
1563
        goto reswitch;
1564
        
1565
        /**************************/
1566
        /* arith & logic */
1567
    case 0x00 ... 0x05:
1568
    case 0x08 ... 0x0d:
1569
    case 0x10 ... 0x15:
1570
    case 0x18 ... 0x1d:
1571
    case 0x20 ... 0x25:
1572
    case 0x28 ... 0x2d:
1573
    case 0x30 ... 0x35:
1574
    case 0x38 ... 0x3d:
1575
        {
1576
            int op, f, val;
1577
            op = (b >> 3) & 7;
1578
            f = (b >> 1) & 3;
1579

    
1580
            if ((b & 1) == 0)
1581
                ot = OT_BYTE;
1582
            else
1583
                ot = dflag ? OT_LONG : OT_WORD;
1584
            
1585
            switch(f) {
1586
            case 0: /* OP Ev, Gv */
1587
                modrm = ldub(s->pc++);
1588
                reg = ((modrm >> 3) & 7);
1589
                mod = (modrm >> 6) & 3;
1590
                rm = modrm & 7;
1591
                if (mod != 3) {
1592
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1593
                    opreg = OR_TMP0;
1594
                } else if (op == OP_XORL && rm == reg) {
1595
                xor_zero:
1596
                    /* xor reg, reg optimisation */
1597
                    gen_op_movl_T0_0();
1598
                    s->cc_op = CC_OP_LOGICB + ot;
1599
                    gen_op_mov_reg_T0[ot][reg]();
1600
                    gen_op_update1_cc();
1601
                    break;
1602
                } else {
1603
                    opreg = rm;
1604
                }
1605
                gen_op_mov_TN_reg[ot][1][reg]();
1606
                gen_op(s, op, ot, opreg);
1607
                break;
1608
            case 1: /* OP Gv, Ev */
1609
                modrm = ldub(s->pc++);
1610
                mod = (modrm >> 6) & 3;
1611
                reg = ((modrm >> 3) & 7);
1612
                rm = modrm & 7;
1613
                if (mod != 3) {
1614
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1615
                    gen_op_ld_T1_A0[ot]();
1616
                } else if (op == OP_XORL && rm == reg) {
1617
                    goto xor_zero;
1618
                } else {
1619
                    gen_op_mov_TN_reg[ot][1][rm]();
1620
                }
1621
                gen_op(s, op, ot, reg);
1622
                break;
1623
            case 2: /* OP A, Iv */
1624
                val = insn_get(s, ot);
1625
                gen_op_movl_T1_im(val);
1626
                gen_op(s, op, ot, OR_EAX);
1627
                break;
1628
            }
1629
        }
1630
        break;
1631

    
1632
    case 0x80: /* GRP1 */
1633
    case 0x81:
1634
    case 0x83:
1635
        {
1636
            int val;
1637

    
1638
            if ((b & 1) == 0)
1639
                ot = OT_BYTE;
1640
            else
1641
                ot = dflag ? OT_LONG : OT_WORD;
1642
            
1643
            modrm = ldub(s->pc++);
1644
            mod = (modrm >> 6) & 3;
1645
            rm = modrm & 7;
1646
            op = (modrm >> 3) & 7;
1647
            
1648
            if (mod != 3) {
1649
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1650
                opreg = OR_TMP0;
1651
            } else {
1652
                opreg = rm + OR_EAX;
1653
            }
1654

    
1655
            switch(b) {
1656
            default:
1657
            case 0x80:
1658
            case 0x81:
1659
                val = insn_get(s, ot);
1660
                break;
1661
            case 0x83:
1662
                val = (int8_t)insn_get(s, OT_BYTE);
1663
                break;
1664
            }
1665
            gen_op_movl_T1_im(val);
1666
            gen_op(s, op, ot, opreg);
1667
        }
1668
        break;
1669

    
1670
        /**************************/
1671
        /* inc, dec, and other misc arith */
1672
    case 0x40 ... 0x47: /* inc Gv */
1673
        ot = dflag ? OT_LONG : OT_WORD;
1674
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1675
        break;
1676
    case 0x48 ... 0x4f: /* dec Gv */
1677
        ot = dflag ? OT_LONG : OT_WORD;
1678
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1679
        break;
1680
    case 0xf6: /* GRP3 */
1681
    case 0xf7:
1682
        if ((b & 1) == 0)
1683
            ot = OT_BYTE;
1684
        else
1685
            ot = dflag ? OT_LONG : OT_WORD;
1686

    
1687
        modrm = ldub(s->pc++);
1688
        mod = (modrm >> 6) & 3;
1689
        rm = modrm & 7;
1690
        op = (modrm >> 3) & 7;
1691
        if (mod != 3) {
1692
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1693
            gen_op_ld_T0_A0[ot]();
1694
        } else {
1695
            gen_op_mov_TN_reg[ot][0][rm]();
1696
        }
1697

    
1698
        switch(op) {
1699
        case 0: /* test */
1700
            val = insn_get(s, ot);
1701
            gen_op_movl_T1_im(val);
1702
            gen_op_testl_T0_T1_cc();
1703
            s->cc_op = CC_OP_LOGICB + ot;
1704
            break;
1705
        case 2: /* not */
1706
            gen_op_notl_T0();
1707
            if (mod != 3) {
1708
                gen_op_st_T0_A0[ot]();
1709
            } else {
1710
                gen_op_mov_reg_T0[ot][rm]();
1711
            }
1712
            break;
1713
        case 3: /* neg */
1714
            gen_op_negl_T0();
1715
            if (mod != 3) {
1716
                gen_op_st_T0_A0[ot]();
1717
            } else {
1718
                gen_op_mov_reg_T0[ot][rm]();
1719
            }
1720
            gen_op_update_neg_cc();
1721
            s->cc_op = CC_OP_SUBB + ot;
1722
            break;
1723
        case 4: /* mul */
1724
            switch(ot) {
1725
            case OT_BYTE:
1726
                gen_op_mulb_AL_T0();
1727
                break;
1728
            case OT_WORD:
1729
                gen_op_mulw_AX_T0();
1730
                break;
1731
            default:
1732
            case OT_LONG:
1733
                gen_op_mull_EAX_T0();
1734
                break;
1735
            }
1736
            s->cc_op = CC_OP_MUL;
1737
            break;
1738
        case 5: /* imul */
1739
            switch(ot) {
1740
            case OT_BYTE:
1741
                gen_op_imulb_AL_T0();
1742
                break;
1743
            case OT_WORD:
1744
                gen_op_imulw_AX_T0();
1745
                break;
1746
            default:
1747
            case OT_LONG:
1748
                gen_op_imull_EAX_T0();
1749
                break;
1750
            }
1751
            s->cc_op = CC_OP_MUL;
1752
            break;
1753
        case 6: /* div */
1754
            switch(ot) {
1755
            case OT_BYTE:
1756
                gen_op_divb_AL_T0(pc_start - s->cs_base);
1757
                break;
1758
            case OT_WORD:
1759
                gen_op_divw_AX_T0(pc_start - s->cs_base);
1760
                break;
1761
            default:
1762
            case OT_LONG:
1763
                gen_op_divl_EAX_T0(pc_start - s->cs_base);
1764
                break;
1765
            }
1766
            break;
1767
        case 7: /* idiv */
1768
            switch(ot) {
1769
            case OT_BYTE:
1770
                gen_op_idivb_AL_T0(pc_start - s->cs_base);
1771
                break;
1772
            case OT_WORD:
1773
                gen_op_idivw_AX_T0(pc_start - s->cs_base);
1774
                break;
1775
            default:
1776
            case OT_LONG:
1777
                gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1778
                break;
1779
            }
1780
            break;
1781
        default:
1782
            goto illegal_op;
1783
        }
1784
        break;
1785

    
1786
    case 0xfe: /* GRP4 */
1787
    case 0xff: /* GRP5 */
1788
        if ((b & 1) == 0)
1789
            ot = OT_BYTE;
1790
        else
1791
            ot = dflag ? OT_LONG : OT_WORD;
1792

    
1793
        modrm = ldub(s->pc++);
1794
        mod = (modrm >> 6) & 3;
1795
        rm = modrm & 7;
1796
        op = (modrm >> 3) & 7;
1797
        if (op >= 2 && b == 0xfe) {
1798
            goto illegal_op;
1799
        }
1800
        if (mod != 3) {
1801
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1802
            if (op >= 2 && op != 3 && op != 5)
1803
                gen_op_ld_T0_A0[ot]();
1804
        } else {
1805
            gen_op_mov_TN_reg[ot][0][rm]();
1806
        }
1807

    
1808
        switch(op) {
1809
        case 0: /* inc Ev */
1810
            if (mod != 3)
1811
                opreg = OR_TMP0;
1812
            else
1813
                opreg = rm;
1814
            gen_inc(s, ot, opreg, 1);
1815
            break;
1816
        case 1: /* dec Ev */
1817
            if (mod != 3)
1818
                opreg = OR_TMP0;
1819
            else
1820
                opreg = rm;
1821
            gen_inc(s, ot, opreg, -1);
1822
            break;
1823
        case 2: /* call Ev */
1824
            /* XXX: optimize if memory (no and is necessary) */
1825
            if (s->dflag == 0)
1826
                gen_op_andl_T0_ffff();
1827
            gen_op_jmp_T0();
1828
            next_eip = s->pc - s->cs_base;
1829
            gen_op_movl_T0_im(next_eip);
1830
            gen_push_T0(s);
1831
            s->is_jmp = 1;
1832
            break;
1833
        case 3: /* lcall Ev */
1834
            /* push return segment + offset */
1835
            gen_op_movl_T0_seg(R_CS);
1836
            gen_push_T0(s);
1837
            next_eip = s->pc - s->cs_base;
1838
            gen_op_movl_T0_im(next_eip);
1839
            gen_push_T0(s);
1840

    
1841
            gen_op_ld_T1_A0[ot]();
1842
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1843
            gen_op_lduw_T0_A0();
1844
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1845
            gen_op_movl_T0_T1();
1846
            gen_op_jmp_T0();
1847
            s->is_jmp = 1;
1848
            break;
1849
        case 4: /* jmp Ev */
1850
            if (s->dflag == 0)
1851
                gen_op_andl_T0_ffff();
1852
            gen_op_jmp_T0();
1853
            s->is_jmp = 1;
1854
            break;
1855
        case 5: /* ljmp Ev */
1856
            gen_op_ld_T1_A0[ot]();
1857
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1858
            gen_op_lduw_T0_A0();
1859
            if (s->pe && !s->vm86) {
1860
                /* we compute EIP to handle the exception case */
1861
                gen_op_jmp_im(pc_start - s->cs_base);
1862
                gen_op_ljmp_T0_T1();
1863
            } else {
1864
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1865
                gen_op_movl_T0_T1();
1866
                gen_op_jmp_T0();
1867
            }
1868
            s->is_jmp = 1;
1869
            break;
1870
        case 6: /* push Ev */
1871
            gen_push_T0(s);
1872
            break;
1873
        default:
1874
            goto illegal_op;
1875
        }
1876
        break;
1877

    
1878
    case 0x84: /* test Ev, Gv */
1879
    case 0x85: 
1880
        if ((b & 1) == 0)
1881
            ot = OT_BYTE;
1882
        else
1883
            ot = dflag ? OT_LONG : OT_WORD;
1884

    
1885
        modrm = ldub(s->pc++);
1886
        mod = (modrm >> 6) & 3;
1887
        rm = modrm & 7;
1888
        reg = (modrm >> 3) & 7;
1889
        
1890
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1891
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1892
        gen_op_testl_T0_T1_cc();
1893
        s->cc_op = CC_OP_LOGICB + ot;
1894
        break;
1895
        
1896
    case 0xa8: /* test eAX, Iv */
1897
    case 0xa9:
1898
        if ((b & 1) == 0)
1899
            ot = OT_BYTE;
1900
        else
1901
            ot = dflag ? OT_LONG : OT_WORD;
1902
        val = insn_get(s, ot);
1903

    
1904
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1905
        gen_op_movl_T1_im(val);
1906
        gen_op_testl_T0_T1_cc();
1907
        s->cc_op = CC_OP_LOGICB + ot;
1908
        break;
1909
        
1910
    case 0x98: /* CWDE/CBW */
1911
        if (dflag)
1912
            gen_op_movswl_EAX_AX();
1913
        else
1914
            gen_op_movsbw_AX_AL();
1915
        break;
1916
    case 0x99: /* CDQ/CWD */
1917
        if (dflag)
1918
            gen_op_movslq_EDX_EAX();
1919
        else
1920
            gen_op_movswl_DX_AX();
1921
        break;
1922
    case 0x1af: /* imul Gv, Ev */
1923
    case 0x69: /* imul Gv, Ev, I */
1924
    case 0x6b:
1925
        ot = dflag ? OT_LONG : OT_WORD;
1926
        modrm = ldub(s->pc++);
1927
        reg = ((modrm >> 3) & 7) + OR_EAX;
1928
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1929
        if (b == 0x69) {
1930
            val = insn_get(s, ot);
1931
            gen_op_movl_T1_im(val);
1932
        } else if (b == 0x6b) {
1933
            val = insn_get(s, OT_BYTE);
1934
            gen_op_movl_T1_im(val);
1935
        } else {
1936
            gen_op_mov_TN_reg[ot][1][reg]();
1937
        }
1938

    
1939
        if (ot == OT_LONG) {
1940
            gen_op_imull_T0_T1();
1941
        } else {
1942
            gen_op_imulw_T0_T1();
1943
        }
1944
        gen_op_mov_reg_T0[ot][reg]();
1945
        s->cc_op = CC_OP_MUL;
1946
        break;
1947
    case 0x1c0:
1948
    case 0x1c1: /* xadd Ev, Gv */
1949
        if ((b & 1) == 0)
1950
            ot = OT_BYTE;
1951
        else
1952
            ot = dflag ? OT_LONG : OT_WORD;
1953
        modrm = ldub(s->pc++);
1954
        reg = (modrm >> 3) & 7;
1955
        mod = (modrm >> 6) & 3;
1956
        if (mod == 3) {
1957
            rm = modrm & 7;
1958
            gen_op_mov_TN_reg[ot][0][reg]();
1959
            gen_op_mov_TN_reg[ot][1][rm]();
1960
            gen_op_addl_T0_T1();
1961
            gen_op_mov_reg_T0[ot][rm]();
1962
            gen_op_mov_reg_T1[ot][reg]();
1963
        } else {
1964
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1965
            gen_op_mov_TN_reg[ot][0][reg]();
1966
            gen_op_ld_T1_A0[ot]();
1967
            gen_op_addl_T0_T1();
1968
            gen_op_st_T0_A0[ot]();
1969
            gen_op_mov_reg_T1[ot][reg]();
1970
        }
1971
        gen_op_update2_cc();
1972
        s->cc_op = CC_OP_ADDB + ot;
1973
        break;
1974
    case 0x1b0:
1975
    case 0x1b1: /* cmpxchg Ev, Gv */
1976
        if ((b & 1) == 0)
1977
            ot = OT_BYTE;
1978
        else
1979
            ot = dflag ? OT_LONG : OT_WORD;
1980
        modrm = ldub(s->pc++);
1981
        reg = (modrm >> 3) & 7;
1982
        mod = (modrm >> 6) & 3;
1983
        gen_op_mov_TN_reg[ot][1][reg]();
1984
        if (mod == 3) {
1985
            rm = modrm & 7;
1986
            gen_op_mov_TN_reg[ot][0][rm]();
1987
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1988
            gen_op_mov_reg_T0[ot][rm]();
1989
        } else {
1990
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1991
            gen_op_ld_T0_A0[ot]();
1992
            gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
1993
        }
1994
        s->cc_op = CC_OP_SUBB + ot;
1995
        break;
1996
    case 0x1c7: /* cmpxchg8b */
1997
        modrm = ldub(s->pc++);
1998
        mod = (modrm >> 6) & 3;
1999
        if (mod == 3)
2000
            goto illegal_op;
2001
        if (s->cc_op != CC_OP_DYNAMIC)
2002
            gen_op_set_cc_op(s->cc_op);
2003
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2004
        gen_op_cmpxchg8b();
2005
        s->cc_op = CC_OP_EFLAGS;
2006
        break;
2007
        
2008
        /**************************/
2009
        /* push/pop */
2010
    case 0x50 ... 0x57: /* push */
2011
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2012
        gen_push_T0(s);
2013
        break;
2014
    case 0x58 ... 0x5f: /* pop */
2015
        ot = dflag ? OT_LONG : OT_WORD;
2016
        gen_pop_T0(s);
2017
        gen_op_mov_reg_T0[ot][b & 7]();
2018
        gen_pop_update(s);
2019
        break;
2020
    case 0x60: /* pusha */
2021
        gen_pusha(s);
2022
        break;
2023
    case 0x61: /* popa */
2024
        gen_popa(s);
2025
        break;
2026
    case 0x68: /* push Iv */
2027
    case 0x6a:
2028
        ot = dflag ? OT_LONG : OT_WORD;
2029
        if (b == 0x68)
2030
            val = insn_get(s, ot);
2031
        else
2032
            val = (int8_t)insn_get(s, OT_BYTE);
2033
        gen_op_movl_T0_im(val);
2034
        gen_push_T0(s);
2035
        break;
2036
    case 0x8f: /* pop Ev */
2037
        ot = dflag ? OT_LONG : OT_WORD;
2038
        modrm = ldub(s->pc++);
2039
        gen_pop_T0(s);
2040
        s->popl_esp_hack = 2 << dflag;
2041
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2042
        s->popl_esp_hack = 0;
2043
        gen_pop_update(s);
2044
        break;
2045
    case 0xc8: /* enter */
2046
        {
2047
            int level;
2048
            val = lduw(s->pc);
2049
            s->pc += 2;
2050
            level = ldub(s->pc++);
2051
            gen_enter(s, val, level);
2052
        }
2053
        break;
2054
    case 0xc9: /* leave */
2055
        /* XXX: exception not precise (ESP is updated before potential exception) */
2056
        if (s->ss32) {
2057
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2058
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2059
        } else {
2060
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2061
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2062
        }
2063
        gen_pop_T0(s);
2064
        ot = dflag ? OT_LONG : OT_WORD;
2065
        gen_op_mov_reg_T0[ot][R_EBP]();
2066
        gen_pop_update(s);
2067
        break;
2068
    case 0x06: /* push es */
2069
    case 0x0e: /* push cs */
2070
    case 0x16: /* push ss */
2071
    case 0x1e: /* push ds */
2072
        gen_op_movl_T0_seg(b >> 3);
2073
        gen_push_T0(s);
2074
        break;
2075
    case 0x1a0: /* push fs */
2076
    case 0x1a8: /* push gs */
2077
        gen_op_movl_T0_seg((b >> 3) & 7);
2078
        gen_push_T0(s);
2079
        break;
2080
    case 0x07: /* pop es */
2081
    case 0x17: /* pop ss */
2082
    case 0x1f: /* pop ds */
2083
        gen_pop_T0(s);
2084
        gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
2085
        gen_pop_update(s);
2086
        /* XXX: if reg == SS, inhibit interrupts/trace */
2087
        break;
2088
    case 0x1a1: /* pop fs */
2089
    case 0x1a9: /* pop gs */
2090
        gen_pop_T0(s);
2091
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2092
        gen_pop_update(s);
2093
        break;
2094

    
2095
        /**************************/
2096
        /* mov */
2097
    case 0x88:
2098
    case 0x89: /* mov Gv, Ev */
2099
        if ((b & 1) == 0)
2100
            ot = OT_BYTE;
2101
        else
2102
            ot = dflag ? OT_LONG : OT_WORD;
2103
        modrm = ldub(s->pc++);
2104
        reg = (modrm >> 3) & 7;
2105
        
2106
        /* generate a generic store */
2107
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2108
        break;
2109
    case 0xc6:
2110
    case 0xc7: /* mov Ev, Iv */
2111
        if ((b & 1) == 0)
2112
            ot = OT_BYTE;
2113
        else
2114
            ot = dflag ? OT_LONG : OT_WORD;
2115
        modrm = ldub(s->pc++);
2116
        mod = (modrm >> 6) & 3;
2117
        if (mod != 3)
2118
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2119
        val = insn_get(s, ot);
2120
        gen_op_movl_T0_im(val);
2121
        if (mod != 3)
2122
            gen_op_st_T0_A0[ot]();
2123
        else
2124
            gen_op_mov_reg_T0[ot][modrm & 7]();
2125
        break;
2126
    case 0x8a:
2127
    case 0x8b: /* mov Ev, Gv */
2128
        if ((b & 1) == 0)
2129
            ot = OT_BYTE;
2130
        else
2131
            ot = dflag ? OT_LONG : OT_WORD;
2132
        modrm = ldub(s->pc++);
2133
        reg = (modrm >> 3) & 7;
2134
        
2135
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2136
        gen_op_mov_reg_T0[ot][reg]();
2137
        break;
2138
    case 0x8e: /* mov seg, Gv */
2139
        modrm = ldub(s->pc++);
2140
        reg = (modrm >> 3) & 7;
2141
        if (reg >= 6 || reg == R_CS)
2142
            goto illegal_op;
2143
        gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2144
        gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2145
        /* XXX: if reg == SS, inhibit interrupts/trace */
2146
        break;
2147
    case 0x8c: /* mov Gv, seg */
2148
        modrm = ldub(s->pc++);
2149
        reg = (modrm >> 3) & 7;
2150
        mod = (modrm >> 6) & 3;
2151
        if (reg >= 6)
2152
            goto illegal_op;
2153
        gen_op_movl_T0_seg(reg);
2154
        ot = OT_WORD;
2155
        if (mod == 3 && dflag)
2156
            ot = OT_LONG;
2157
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2158
        break;
2159

    
2160
    case 0x1b6: /* movzbS Gv, Eb */
2161
    case 0x1b7: /* movzwS Gv, Eb */
2162
    case 0x1be: /* movsbS Gv, Eb */
2163
    case 0x1bf: /* movswS Gv, Eb */
2164
        {
2165
            int d_ot;
2166
            /* d_ot is the size of destination */
2167
            d_ot = dflag + OT_WORD;
2168
            /* ot is the size of source */
2169
            ot = (b & 1) + OT_BYTE;
2170
            modrm = ldub(s->pc++);
2171
            reg = ((modrm >> 3) & 7) + OR_EAX;
2172
            mod = (modrm >> 6) & 3;
2173
            rm = modrm & 7;
2174
            
2175
            if (mod == 3) {
2176
                gen_op_mov_TN_reg[ot][0][rm]();
2177
                switch(ot | (b & 8)) {
2178
                case OT_BYTE:
2179
                    gen_op_movzbl_T0_T0();
2180
                    break;
2181
                case OT_BYTE | 8:
2182
                    gen_op_movsbl_T0_T0();
2183
                    break;
2184
                case OT_WORD:
2185
                    gen_op_movzwl_T0_T0();
2186
                    break;
2187
                default:
2188
                case OT_WORD | 8:
2189
                    gen_op_movswl_T0_T0();
2190
                    break;
2191
                }
2192
                gen_op_mov_reg_T0[d_ot][reg]();
2193
            } else {
2194
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2195
                if (b & 8) {
2196
                    gen_op_lds_T0_A0[ot]();
2197
                } else {
2198
                    gen_op_ldu_T0_A0[ot]();
2199
                }
2200
                gen_op_mov_reg_T0[d_ot][reg]();
2201
            }
2202
        }
2203
        break;
2204

    
2205
    case 0x8d: /* lea */
2206
        ot = dflag ? OT_LONG : OT_WORD;
2207
        modrm = ldub(s->pc++);
2208
        reg = (modrm >> 3) & 7;
2209
        /* we must ensure that no segment is added */
2210
        s->override = -1;
2211
        val = s->addseg;
2212
        s->addseg = 0;
2213
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2214
        s->addseg = val;
2215
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2216
        break;
2217
        
2218
    case 0xa0: /* mov EAX, Ov */
2219
    case 0xa1:
2220
    case 0xa2: /* mov Ov, EAX */
2221
    case 0xa3:
2222
        if ((b & 1) == 0)
2223
            ot = OT_BYTE;
2224
        else
2225
            ot = dflag ? OT_LONG : OT_WORD;
2226
        if (s->aflag)
2227
            offset_addr = insn_get(s, OT_LONG);
2228
        else
2229
            offset_addr = insn_get(s, OT_WORD);
2230
        gen_op_movl_A0_im(offset_addr);
2231
        /* handle override */
2232
        {
2233
            int override, must_add_seg;
2234
            must_add_seg = s->addseg;
2235
            if (s->override >= 0) {
2236
                override = s->override;
2237
                must_add_seg = 1;
2238
            } else {
2239
                override = R_DS;
2240
            }
2241
            if (must_add_seg) {
2242
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2243
            }
2244
        }
2245
        if ((b & 2) == 0) {
2246
            gen_op_ld_T0_A0[ot]();
2247
            gen_op_mov_reg_T0[ot][R_EAX]();
2248
        } else {
2249
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2250
            gen_op_st_T0_A0[ot]();
2251
        }
2252
        break;
2253
    case 0xd7: /* xlat */
2254
        gen_op_movl_A0_reg[R_EBX]();
2255
        gen_op_addl_A0_AL();
2256
        if (s->aflag == 0)
2257
            gen_op_andl_A0_ffff();
2258
        /* handle override */
2259
        {
2260
            int override, must_add_seg;
2261
            must_add_seg = s->addseg;
2262
            override = R_DS;
2263
            if (s->override >= 0) {
2264
                override = s->override;
2265
                must_add_seg = 1;
2266
            } else {
2267
                override = R_DS;
2268
            }
2269
            if (must_add_seg) {
2270
                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2271
            }
2272
        }
2273
        gen_op_ldub_T0_A0();
2274
        gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2275
        break;
2276
    case 0xb0 ... 0xb7: /* mov R, Ib */
2277
        val = insn_get(s, OT_BYTE);
2278
        gen_op_movl_T0_im(val);
2279
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2280
        break;
2281
    case 0xb8 ... 0xbf: /* mov R, Iv */
2282
        ot = dflag ? OT_LONG : OT_WORD;
2283
        val = insn_get(s, ot);
2284
        reg = OR_EAX + (b & 7);
2285
        gen_op_movl_T0_im(val);
2286
        gen_op_mov_reg_T0[ot][reg]();
2287
        break;
2288

    
2289
    case 0x91 ... 0x97: /* xchg R, EAX */
2290
        ot = dflag ? OT_LONG : OT_WORD;
2291
        reg = b & 7;
2292
        rm = R_EAX;
2293
        goto do_xchg_reg;
2294
    case 0x86:
2295
    case 0x87: /* xchg Ev, Gv */
2296
        if ((b & 1) == 0)
2297
            ot = OT_BYTE;
2298
        else
2299
            ot = dflag ? OT_LONG : OT_WORD;
2300
        modrm = ldub(s->pc++);
2301
        reg = (modrm >> 3) & 7;
2302
        mod = (modrm >> 6) & 3;
2303
        if (mod == 3) {
2304
            rm = modrm & 7;
2305
        do_xchg_reg:
2306
            gen_op_mov_TN_reg[ot][0][reg]();
2307
            gen_op_mov_TN_reg[ot][1][rm]();
2308
            gen_op_mov_reg_T0[ot][rm]();
2309
            gen_op_mov_reg_T1[ot][reg]();
2310
        } else {
2311
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2312
            gen_op_mov_TN_reg[ot][0][reg]();
2313
            /* for xchg, lock is implicit */
2314
            if (!(prefixes & PREFIX_LOCK))
2315
                gen_op_lock();
2316
            gen_op_ld_T1_A0[ot]();
2317
            gen_op_st_T0_A0[ot]();
2318
            if (!(prefixes & PREFIX_LOCK))
2319
                gen_op_unlock();
2320
            gen_op_mov_reg_T1[ot][reg]();
2321
        }
2322
        break;
2323
    case 0xc4: /* les Gv */
2324
        op = R_ES;
2325
        goto do_lxx;
2326
    case 0xc5: /* lds Gv */
2327
        op = R_DS;
2328
        goto do_lxx;
2329
    case 0x1b2: /* lss Gv */
2330
        op = R_SS;
2331
        goto do_lxx;
2332
    case 0x1b4: /* lfs Gv */
2333
        op = R_FS;
2334
        goto do_lxx;
2335
    case 0x1b5: /* lgs Gv */
2336
        op = R_GS;
2337
    do_lxx:
2338
        ot = dflag ? OT_LONG : OT_WORD;
2339
        modrm = ldub(s->pc++);
2340
        reg = (modrm >> 3) & 7;
2341
        mod = (modrm >> 6) & 3;
2342
        if (mod == 3)
2343
            goto illegal_op;
2344
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2345
        gen_op_ld_T1_A0[ot]();
2346
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2347
        /* load the segment first to handle exceptions properly */
2348
        gen_op_lduw_T0_A0();
2349
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2350
        /* then put the data */
2351
        gen_op_mov_reg_T1[ot][reg]();
2352
        break;
2353
        
2354
        /************************/
2355
        /* shifts */
2356
    case 0xc0:
2357
    case 0xc1:
2358
        /* shift Ev,Ib */
2359
        shift = 2;
2360
    grp2:
2361
        {
2362
            if ((b & 1) == 0)
2363
                ot = OT_BYTE;
2364
            else
2365
                ot = dflag ? OT_LONG : OT_WORD;
2366
            
2367
            modrm = ldub(s->pc++);
2368
            mod = (modrm >> 6) & 3;
2369
            rm = modrm & 7;
2370
            op = (modrm >> 3) & 7;
2371
            
2372
            if (mod != 3) {
2373
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2374
                opreg = OR_TMP0;
2375
            } else {
2376
                opreg = rm + OR_EAX;
2377
            }
2378

    
2379
            /* simpler op */
2380
            if (shift == 0) {
2381
                gen_shift(s, op, ot, opreg, OR_ECX);
2382
            } else {
2383
                if (shift == 2) {
2384
                    shift = ldub(s->pc++);
2385
                }
2386
                gen_shifti(s, op, ot, opreg, shift);
2387
            }
2388
        }
2389
        break;
2390
    case 0xd0:
2391
    case 0xd1:
2392
        /* shift Ev,1 */
2393
        shift = 1;
2394
        goto grp2;
2395
    case 0xd2:
2396
    case 0xd3:
2397
        /* shift Ev,cl */
2398
        shift = 0;
2399
        goto grp2;
2400

    
2401
    case 0x1a4: /* shld imm */
2402
        op = 0;
2403
        shift = 1;
2404
        goto do_shiftd;
2405
    case 0x1a5: /* shld cl */
2406
        op = 0;
2407
        shift = 0;
2408
        goto do_shiftd;
2409
    case 0x1ac: /* shrd imm */
2410
        op = 1;
2411
        shift = 1;
2412
        goto do_shiftd;
2413
    case 0x1ad: /* shrd cl */
2414
        op = 1;
2415
        shift = 0;
2416
    do_shiftd:
2417
        ot = dflag ? OT_LONG : OT_WORD;
2418
        modrm = ldub(s->pc++);
2419
        mod = (modrm >> 6) & 3;
2420
        rm = modrm & 7;
2421
        reg = (modrm >> 3) & 7;
2422
        
2423
        if (mod != 3) {
2424
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2425
            gen_op_ld_T0_A0[ot]();
2426
        } else {
2427
            gen_op_mov_TN_reg[ot][0][rm]();
2428
        }
2429
        gen_op_mov_TN_reg[ot][1][reg]();
2430
        
2431
        if (shift) {
2432
            val = ldub(s->pc++);
2433
            val &= 0x1f;
2434
            if (val) {
2435
                if (mod == 3)
2436
                    gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2437
                else
2438
                    gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
2439
                if (op == 0 && ot != OT_WORD)
2440
                    s->cc_op = CC_OP_SHLB + ot;
2441
                else
2442
                    s->cc_op = CC_OP_SARB + ot;
2443
            }
2444
        } else {
2445
            if (s->cc_op != CC_OP_DYNAMIC)
2446
                gen_op_set_cc_op(s->cc_op);
2447
            if (mod == 3)
2448
                gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2449
            else
2450
                gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
2451
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2452
        }
2453
        if (mod == 3) {
2454
            gen_op_mov_reg_T0[ot][rm]();
2455
        }
2456
        break;
2457

    
2458
        /************************/
2459
        /* floats */
2460
    case 0xd8 ... 0xdf: 
2461
        modrm = ldub(s->pc++);
2462
        mod = (modrm >> 6) & 3;
2463
        rm = modrm & 7;
2464
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2465
        
2466
        if (mod != 3) {
2467
            /* memory op */
2468
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2469
            switch(op) {
2470
            case 0x00 ... 0x07: /* fxxxs */
2471
            case 0x10 ... 0x17: /* fixxxl */
2472
            case 0x20 ... 0x27: /* fxxxl */
2473
            case 0x30 ... 0x37: /* fixxx */
2474
                {
2475
                    int op1;
2476
                    op1 = op & 7;
2477

    
2478
                    switch(op >> 4) {
2479
                    case 0:
2480
                        gen_op_flds_FT0_A0();
2481
                        break;
2482
                    case 1:
2483
                        gen_op_fildl_FT0_A0();
2484
                        break;
2485
                    case 2:
2486
                        gen_op_fldl_FT0_A0();
2487
                        break;
2488
                    case 3:
2489
                    default:
2490
                        gen_op_fild_FT0_A0();
2491
                        break;
2492
                    }
2493
                    
2494
                    gen_op_fp_arith_ST0_FT0[op1]();
2495
                    if (op1 == 3) {
2496
                        /* fcomp needs pop */
2497
                        gen_op_fpop();
2498
                    }
2499
                }
2500
                break;
2501
            case 0x08: /* flds */
2502
            case 0x0a: /* fsts */
2503
            case 0x0b: /* fstps */
2504
            case 0x18: /* fildl */
2505
            case 0x1a: /* fistl */
2506
            case 0x1b: /* fistpl */
2507
            case 0x28: /* fldl */
2508
            case 0x2a: /* fstl */
2509
            case 0x2b: /* fstpl */
2510
            case 0x38: /* filds */
2511
            case 0x3a: /* fists */
2512
            case 0x3b: /* fistps */
2513
                
2514
                switch(op & 7) {
2515
                case 0:
2516
                    switch(op >> 4) {
2517
                    case 0:
2518
                        gen_op_flds_ST0_A0();
2519
                        break;
2520
                    case 1:
2521
                        gen_op_fildl_ST0_A0();
2522
                        break;
2523
                    case 2:
2524
                        gen_op_fldl_ST0_A0();
2525
                        break;
2526
                    case 3:
2527
                    default:
2528
                        gen_op_fild_ST0_A0();
2529
                        break;
2530
                    }
2531
                    break;
2532
                default:
2533
                    switch(op >> 4) {
2534
                    case 0:
2535
                        gen_op_fsts_ST0_A0();
2536
                        break;
2537
                    case 1:
2538
                        gen_op_fistl_ST0_A0();
2539
                        break;
2540
                    case 2:
2541
                        gen_op_fstl_ST0_A0();
2542
                        break;
2543
                    case 3:
2544
                    default:
2545
                        gen_op_fist_ST0_A0();
2546
                        break;
2547
                    }
2548
                    if ((op & 7) == 3)
2549
                        gen_op_fpop();
2550
                    break;
2551
                }
2552
                break;
2553
            case 0x0c: /* fldenv mem */
2554
                gen_op_fldenv_A0(s->dflag);
2555
                break;
2556
            case 0x0d: /* fldcw mem */
2557
                gen_op_fldcw_A0();
2558
                break;
2559
            case 0x0e: /* fnstenv mem */
2560
                gen_op_fnstenv_A0(s->dflag);
2561
                break;
2562
            case 0x0f: /* fnstcw mem */
2563
                gen_op_fnstcw_A0();
2564
                break;
2565
            case 0x1d: /* fldt mem */
2566
                gen_op_fldt_ST0_A0();
2567
                break;
2568
            case 0x1f: /* fstpt mem */
2569
                gen_op_fstt_ST0_A0();
2570
                gen_op_fpop();
2571
                break;
2572
            case 0x2c: /* frstor mem */
2573
                gen_op_frstor_A0(s->dflag);
2574
                break;
2575
            case 0x2e: /* fnsave mem */
2576
                gen_op_fnsave_A0(s->dflag);
2577
                break;
2578
            case 0x2f: /* fnstsw mem */
2579
                gen_op_fnstsw_A0();
2580
                break;
2581
            case 0x3c: /* fbld */
2582
                gen_op_fbld_ST0_A0();
2583
                break;
2584
            case 0x3e: /* fbstp */
2585
                gen_op_fbst_ST0_A0();
2586
                gen_op_fpop();
2587
                break;
2588
            case 0x3d: /* fildll */
2589
                gen_op_fildll_ST0_A0();
2590
                break;
2591
            case 0x3f: /* fistpll */
2592
                gen_op_fistll_ST0_A0();
2593
                gen_op_fpop();
2594
                break;
2595
            default:
2596
                goto illegal_op;
2597
            }
2598
        } else {
2599
            /* register float ops */
2600
            opreg = rm;
2601

    
2602
            switch(op) {
2603
            case 0x08: /* fld sti */
2604
                gen_op_fpush();
2605
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2606
                break;
2607
            case 0x09: /* fxchg sti */
2608
                gen_op_fxchg_ST0_STN(opreg);
2609
                break;
2610
            case 0x0a: /* grp d9/2 */
2611
                switch(rm) {
2612
                case 0: /* fnop */
2613
                    break;
2614
                default:
2615
                    goto illegal_op;
2616
                }
2617
                break;
2618
            case 0x0c: /* grp d9/4 */
2619
                switch(rm) {
2620
                case 0: /* fchs */
2621
                    gen_op_fchs_ST0();
2622
                    break;
2623
                case 1: /* fabs */
2624
                    gen_op_fabs_ST0();
2625
                    break;
2626
                case 4: /* ftst */
2627
                    gen_op_fldz_FT0();
2628
                    gen_op_fcom_ST0_FT0();
2629
                    break;
2630
                case 5: /* fxam */
2631
                    gen_op_fxam_ST0();
2632
                    break;
2633
                default:
2634
                    goto illegal_op;
2635
                }
2636
                break;
2637
            case 0x0d: /* grp d9/5 */
2638
                {
2639
                    switch(rm) {
2640
                    case 0:
2641
                        gen_op_fpush();
2642
                        gen_op_fld1_ST0();
2643
                        break;
2644
                    case 1:
2645
                        gen_op_fpush();
2646
                        gen_op_fldl2t_ST0();
2647
                        break;
2648
                    case 2:
2649
                        gen_op_fpush();
2650
                        gen_op_fldl2e_ST0();
2651
                        break;
2652
                    case 3:
2653
                        gen_op_fpush();
2654
                        gen_op_fldpi_ST0();
2655
                        break;
2656
                    case 4:
2657
                        gen_op_fpush();
2658
                        gen_op_fldlg2_ST0();
2659
                        break;
2660
                    case 5:
2661
                        gen_op_fpush();
2662
                        gen_op_fldln2_ST0();
2663
                        break;
2664
                    case 6:
2665
                        gen_op_fpush();
2666
                        gen_op_fldz_ST0();
2667
                        break;
2668
                    default:
2669
                        goto illegal_op;
2670
                    }
2671
                }
2672
                break;
2673
            case 0x0e: /* grp d9/6 */
2674
                switch(rm) {
2675
                case 0: /* f2xm1 */
2676
                    gen_op_f2xm1();
2677
                    break;
2678
                case 1: /* fyl2x */
2679
                    gen_op_fyl2x();
2680
                    break;
2681
                case 2: /* fptan */
2682
                    gen_op_fptan();
2683
                    break;
2684
                case 3: /* fpatan */
2685
                    gen_op_fpatan();
2686
                    break;
2687
                case 4: /* fxtract */
2688
                    gen_op_fxtract();
2689
                    break;
2690
                case 5: /* fprem1 */
2691
                    gen_op_fprem1();
2692
                    break;
2693
                case 6: /* fdecstp */
2694
                    gen_op_fdecstp();
2695
                    break;
2696
                default:
2697
                case 7: /* fincstp */
2698
                    gen_op_fincstp();
2699
                    break;
2700
                }
2701
                break;
2702
            case 0x0f: /* grp d9/7 */
2703
                switch(rm) {
2704
                case 0: /* fprem */
2705
                    gen_op_fprem();
2706
                    break;
2707
                case 1: /* fyl2xp1 */
2708
                    gen_op_fyl2xp1();
2709
                    break;
2710
                case 2: /* fsqrt */
2711
                    gen_op_fsqrt();
2712
                    break;
2713
                case 3: /* fsincos */
2714
                    gen_op_fsincos();
2715
                    break;
2716
                case 5: /* fscale */
2717
                    gen_op_fscale();
2718
                    break;
2719
                case 4: /* frndint */
2720
                    gen_op_frndint();
2721
                    break;
2722
                case 6: /* fsin */
2723
                    gen_op_fsin();
2724
                    break;
2725
                default:
2726
                case 7: /* fcos */
2727
                    gen_op_fcos();
2728
                    break;
2729
                }
2730
                break;
2731
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2732
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2733
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2734
                {
2735
                    int op1;
2736
                    
2737
                    op1 = op & 7;
2738
                    if (op >= 0x20) {
2739
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2740
                        if (op >= 0x30)
2741
                            gen_op_fpop();
2742
                    } else {
2743
                        gen_op_fmov_FT0_STN(opreg);
2744
                        gen_op_fp_arith_ST0_FT0[op1]();
2745
                    }
2746
                }
2747
                break;
2748
            case 0x02: /* fcom */
2749
                gen_op_fmov_FT0_STN(opreg);
2750
                gen_op_fcom_ST0_FT0();
2751
                break;
2752
            case 0x03: /* fcomp */
2753
                gen_op_fmov_FT0_STN(opreg);
2754
                gen_op_fcom_ST0_FT0();
2755
                gen_op_fpop();
2756
                break;
2757
            case 0x15: /* da/5 */
2758
                switch(rm) {
2759
                case 1: /* fucompp */
2760
                    gen_op_fmov_FT0_STN(1);
2761
                    gen_op_fucom_ST0_FT0();
2762
                    gen_op_fpop();
2763
                    gen_op_fpop();
2764
                    break;
2765
                default:
2766
                    goto illegal_op;
2767
                }
2768
                break;
2769
            case 0x1c:
2770
                switch(rm) {
2771
                case 0: /* feni (287 only, just do nop here) */
2772
                    break;
2773
                case 1: /* fdisi (287 only, just do nop here) */
2774
                    break;
2775
                case 2: /* fclex */
2776
                    gen_op_fclex();
2777
                    break;
2778
                case 3: /* fninit */
2779
                    gen_op_fninit();
2780
                    break;
2781
                case 4: /* fsetpm (287 only, just do nop here) */
2782
                    break;
2783
                default:
2784
                    goto illegal_op;
2785
                }
2786
                break;
2787
            case 0x1d: /* fucomi */
2788
                if (s->cc_op != CC_OP_DYNAMIC)
2789
                    gen_op_set_cc_op(s->cc_op);
2790
                gen_op_fmov_FT0_STN(opreg);
2791
                gen_op_fucomi_ST0_FT0();
2792
                s->cc_op = CC_OP_EFLAGS;
2793
                break;
2794
            case 0x1e: /* fcomi */
2795
                if (s->cc_op != CC_OP_DYNAMIC)
2796
                    gen_op_set_cc_op(s->cc_op);
2797
                gen_op_fmov_FT0_STN(opreg);
2798
                gen_op_fcomi_ST0_FT0();
2799
                s->cc_op = CC_OP_EFLAGS;
2800
                break;
2801
            case 0x2a: /* fst sti */
2802
                gen_op_fmov_STN_ST0(opreg);
2803
                break;
2804
            case 0x2b: /* fstp sti */
2805
                gen_op_fmov_STN_ST0(opreg);
2806
                gen_op_fpop();
2807
                break;
2808
            case 0x2c: /* fucom st(i) */
2809
                gen_op_fmov_FT0_STN(opreg);
2810
                gen_op_fucom_ST0_FT0();
2811
                break;
2812
            case 0x2d: /* fucomp st(i) */
2813
                gen_op_fmov_FT0_STN(opreg);
2814
                gen_op_fucom_ST0_FT0();
2815
                gen_op_fpop();
2816
                break;
2817
            case 0x33: /* de/3 */
2818
                switch(rm) {
2819
                case 1: /* fcompp */
2820
                    gen_op_fmov_FT0_STN(1);
2821
                    gen_op_fcom_ST0_FT0();
2822
                    gen_op_fpop();
2823
                    gen_op_fpop();
2824
                    break;
2825
                default:
2826
                    goto illegal_op;
2827
                }
2828
                break;
2829
            case 0x3c: /* df/4 */
2830
                switch(rm) {
2831
                case 0:
2832
                    gen_op_fnstsw_EAX();
2833
                    break;
2834
                default:
2835
                    goto illegal_op;
2836
                }
2837
                break;
2838
            case 0x3d: /* fucomip */
2839
                if (s->cc_op != CC_OP_DYNAMIC)
2840
                    gen_op_set_cc_op(s->cc_op);
2841
                gen_op_fmov_FT0_STN(opreg);
2842
                gen_op_fucomi_ST0_FT0();
2843
                gen_op_fpop();
2844
                s->cc_op = CC_OP_EFLAGS;
2845
                break;
2846
            case 0x3e: /* fcomip */
2847
                if (s->cc_op != CC_OP_DYNAMIC)
2848
                    gen_op_set_cc_op(s->cc_op);
2849
                gen_op_fmov_FT0_STN(opreg);
2850
                gen_op_fcomi_ST0_FT0();
2851
                gen_op_fpop();
2852
                s->cc_op = CC_OP_EFLAGS;
2853
                break;
2854
            default:
2855
                goto illegal_op;
2856
            }
2857
        }
2858
        break;
2859
        /************************/
2860
        /* string ops */
2861

    
2862
    case 0xa4: /* movsS */
2863
    case 0xa5:
2864
        if ((b & 1) == 0)
2865
            ot = OT_BYTE;
2866
        else
2867
            ot = dflag ? OT_LONG : OT_WORD;
2868

    
2869
        if (prefixes & PREFIX_REPZ) {
2870
            gen_string_ds(s, ot, gen_op_movs + 9);
2871
        } else {
2872
            gen_string_ds(s, ot, gen_op_movs);
2873
        }
2874
        break;
2875
        
2876
    case 0xaa: /* stosS */
2877
    case 0xab:
2878
        if ((b & 1) == 0)
2879
            ot = OT_BYTE;
2880
        else
2881
            ot = dflag ? OT_LONG : OT_WORD;
2882

    
2883
        if (prefixes & PREFIX_REPZ) {
2884
            gen_string_es(s, ot, gen_op_stos + 9);
2885
        } else {
2886
            gen_string_es(s, ot, gen_op_stos);
2887
        }
2888
        break;
2889
    case 0xac: /* lodsS */
2890
    case 0xad:
2891
        if ((b & 1) == 0)
2892
            ot = OT_BYTE;
2893
        else
2894
            ot = dflag ? OT_LONG : OT_WORD;
2895
        if (prefixes & PREFIX_REPZ) {
2896
            gen_string_ds(s, ot, gen_op_lods + 9);
2897
        } else {
2898
            gen_string_ds(s, ot, gen_op_lods);
2899
        }
2900
        break;
2901
    case 0xae: /* scasS */
2902
    case 0xaf:
2903
        if ((b & 1) == 0)
2904
            ot = OT_BYTE;
2905
        else
2906
                ot = dflag ? OT_LONG : OT_WORD;
2907
        if (prefixes & PREFIX_REPNZ) {
2908
            if (s->cc_op != CC_OP_DYNAMIC)
2909
                gen_op_set_cc_op(s->cc_op);
2910
            gen_string_es(s, ot, gen_op_scas + 9 * 2);
2911
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2912
        } else if (prefixes & PREFIX_REPZ) {
2913
            if (s->cc_op != CC_OP_DYNAMIC)
2914
                gen_op_set_cc_op(s->cc_op);
2915
            gen_string_es(s, ot, gen_op_scas + 9);
2916
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2917
        } else {
2918
            gen_string_es(s, ot, gen_op_scas);
2919
            s->cc_op = CC_OP_SUBB + ot;
2920
        }
2921
        break;
2922

    
2923
    case 0xa6: /* cmpsS */
2924
    case 0xa7:
2925
        if ((b & 1) == 0)
2926
            ot = OT_BYTE;
2927
        else
2928
            ot = dflag ? OT_LONG : OT_WORD;
2929
        if (prefixes & PREFIX_REPNZ) {
2930
            if (s->cc_op != CC_OP_DYNAMIC)
2931
                gen_op_set_cc_op(s->cc_op);
2932
            gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2933
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2934
        } else if (prefixes & PREFIX_REPZ) {
2935
            if (s->cc_op != CC_OP_DYNAMIC)
2936
                gen_op_set_cc_op(s->cc_op);
2937
            gen_string_ds(s, ot, gen_op_cmps + 9);
2938
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2939
        } else {
2940
            gen_string_ds(s, ot, gen_op_cmps);
2941
            s->cc_op = CC_OP_SUBB + ot;
2942
        }
2943
        break;
2944
    case 0x6c: /* insS */
2945
    case 0x6d:
2946
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2947
            /* NOTE: even for (E)CX = 0 the exception is raised */
2948
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2949
        } else {
2950
            if ((b & 1) == 0)
2951
                ot = OT_BYTE;
2952
            else
2953
                ot = dflag ? OT_LONG : OT_WORD;
2954
            if (prefixes & PREFIX_REPZ) {
2955
                gen_string_es(s, ot, gen_op_ins + 9);
2956
            } else {
2957
                gen_string_es(s, ot, gen_op_ins);
2958
            }
2959
        }
2960
        break;
2961
    case 0x6e: /* outsS */
2962
    case 0x6f:
2963
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2964
            /* NOTE: even for (E)CX = 0 the exception is raised */
2965
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2966
        } else {
2967
            if ((b & 1) == 0)
2968
                ot = OT_BYTE;
2969
            else
2970
                ot = dflag ? OT_LONG : OT_WORD;
2971
            if (prefixes & PREFIX_REPZ) {
2972
                gen_string_ds(s, ot, gen_op_outs + 9);
2973
            } else {
2974
                gen_string_ds(s, ot, gen_op_outs);
2975
            }
2976
        }
2977
        break;
2978

    
2979
        /************************/
2980
        /* port I/O */
2981
    case 0xe4:
2982
    case 0xe5:
2983
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2984
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2985
        } else {
2986
            if ((b & 1) == 0)
2987
                ot = OT_BYTE;
2988
            else
2989
                ot = dflag ? OT_LONG : OT_WORD;
2990
            val = ldub(s->pc++);
2991
            gen_op_movl_T0_im(val);
2992
            gen_op_in[ot]();
2993
            gen_op_mov_reg_T1[ot][R_EAX]();
2994
        }
2995
        break;
2996
    case 0xe6:
2997
    case 0xe7:
2998
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2999
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3000
        } else {
3001
            if ((b & 1) == 0)
3002
                ot = OT_BYTE;
3003
            else
3004
                ot = dflag ? OT_LONG : OT_WORD;
3005
            val = ldub(s->pc++);
3006
            gen_op_movl_T0_im(val);
3007
            gen_op_mov_TN_reg[ot][1][R_EAX]();
3008
            gen_op_out[ot]();
3009
        }
3010
        break;
3011
    case 0xec:
3012
    case 0xed:
3013
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3014
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3015
        } else {
3016
            if ((b & 1) == 0)
3017
                ot = OT_BYTE;
3018
            else
3019
                ot = dflag ? OT_LONG : OT_WORD;
3020
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3021
            gen_op_in[ot]();
3022
            gen_op_mov_reg_T1[ot][R_EAX]();
3023
        }
3024
        break;
3025
    case 0xee:
3026
    case 0xef:
3027
        if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3028
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3029
        } else {
3030
            if ((b & 1) == 0)
3031
                ot = OT_BYTE;
3032
            else
3033
                ot = dflag ? OT_LONG : OT_WORD;
3034
            gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3035
            gen_op_mov_TN_reg[ot][1][R_EAX]();
3036
            gen_op_out[ot]();
3037
        }
3038
        break;
3039

    
3040
        /************************/
3041
        /* control */
3042
    case 0xc2: /* ret im */
3043
        val = ldsw(s->pc);
3044
        s->pc += 2;
3045
        gen_pop_T0(s);
3046
        gen_stack_update(s, val + (2 << s->dflag));
3047
        if (s->dflag == 0)
3048
            gen_op_andl_T0_ffff();
3049
        gen_op_jmp_T0();
3050
        s->is_jmp = 1;
3051
        break;
3052
    case 0xc3: /* ret */
3053
        gen_pop_T0(s);
3054
        gen_pop_update(s);
3055
        if (s->dflag == 0)
3056
            gen_op_andl_T0_ffff();
3057
        gen_op_jmp_T0();
3058
        s->is_jmp = 1;
3059
        break;
3060
    case 0xca: /* lret im */
3061
        val = ldsw(s->pc);
3062
        s->pc += 2;
3063
    do_lret:
3064
        gen_stack_A0(s);
3065
        /* pop offset */
3066
        gen_op_ld_T0_A0[1 + s->dflag]();
3067
        if (s->dflag == 0)
3068
            gen_op_andl_T0_ffff();
3069
        /* NOTE: keeping EIP updated is not a problem in case of
3070
           exception */
3071
        gen_op_jmp_T0();
3072
        /* pop selector */
3073
        gen_op_addl_A0_im(2 << s->dflag);
3074
        gen_op_ld_T0_A0[1 + s->dflag]();
3075
        gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3076
        /* add stack offset */
3077
        gen_stack_update(s, val + (4 << s->dflag));
3078
        s->is_jmp = 1;
3079
        break;
3080
    case 0xcb: /* lret */
3081
        val = 0;
3082
        goto do_lret;
3083
    case 0xcf: /* iret */
3084
        if (!s->pe) {
3085
            /* real mode */
3086
            gen_op_iret_real(s->dflag);
3087
            s->cc_op = CC_OP_EFLAGS;
3088
        } else if (s->vm86 && s->iopl != 3) {
3089
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3090
        } else {
3091
            if (s->cc_op != CC_OP_DYNAMIC)
3092
                gen_op_set_cc_op(s->cc_op);
3093
            gen_op_jmp_im(pc_start - s->cs_base);
3094
            gen_op_iret_protected(s->dflag);
3095
            s->cc_op = CC_OP_EFLAGS;
3096
        }
3097
        s->is_jmp = 1;
3098
        break;
3099
    case 0xe8: /* call im */
3100
        {
3101
            unsigned int next_eip;
3102
            ot = dflag ? OT_LONG : OT_WORD;
3103
            val = insn_get(s, ot);
3104
            next_eip = s->pc - s->cs_base;
3105
            val += next_eip;
3106
            if (s->dflag == 0)
3107
                val &= 0xffff;
3108
            gen_op_movl_T0_im(next_eip);
3109
            gen_push_T0(s);
3110
            gen_jmp(s, val);
3111
        }
3112
        break;
3113
    case 0x9a: /* lcall im */
3114
        {
3115
            unsigned int selector, offset;
3116
            /* XXX: not restartable */
3117

    
3118
            ot = dflag ? OT_LONG : OT_WORD;
3119
            offset = insn_get(s, ot);
3120
            selector = insn_get(s, OT_WORD);
3121
            
3122
            /* push return segment + offset */
3123
            gen_op_movl_T0_seg(R_CS);
3124
            gen_push_T0(s);
3125
            next_eip = s->pc - s->cs_base;
3126
            gen_op_movl_T0_im(next_eip);
3127
            gen_push_T0(s);
3128

    
3129
            /* change cs and pc */
3130
            gen_op_movl_T0_im(selector);
3131
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3132
            gen_op_jmp_im((unsigned long)offset);
3133
            s->is_jmp = 1;
3134
        }
3135
        break;
3136
    case 0xe9: /* jmp */
3137
        ot = dflag ? OT_LONG : OT_WORD;
3138
        val = insn_get(s, ot);
3139
        val += s->pc - s->cs_base;
3140
        if (s->dflag == 0)
3141
            val = val & 0xffff;
3142
        gen_jmp(s, val);
3143
        break;
3144
    case 0xea: /* ljmp im */
3145
        {
3146
            unsigned int selector, offset;
3147

    
3148
            ot = dflag ? OT_LONG : OT_WORD;
3149
            offset = insn_get(s, ot);
3150
            selector = insn_get(s, OT_WORD);
3151
            
3152
            /* change cs and pc */
3153
            gen_op_movl_T0_im(selector);
3154
            if (s->pe && !s->vm86) {
3155
                /* we compute EIP to handle the exception case */
3156
                gen_op_jmp_im(pc_start - s->cs_base);
3157
                gen_op_movl_T1_im(offset);
3158
                gen_op_ljmp_T0_T1();
3159
            } else {
3160
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3161
                gen_op_jmp_im((unsigned long)offset);
3162
            }
3163
            s->is_jmp = 1;
3164
        }
3165
        break;
3166
    case 0xeb: /* jmp Jb */
3167
        val = (int8_t)insn_get(s, OT_BYTE);
3168
        val += s->pc - s->cs_base;
3169
        if (s->dflag == 0)
3170
            val = val & 0xffff;
3171
        gen_jmp(s, val);
3172
        break;
3173
    case 0x70 ... 0x7f: /* jcc Jb */
3174
        val = (int8_t)insn_get(s, OT_BYTE);
3175
        goto do_jcc;
3176
    case 0x180 ... 0x18f: /* jcc Jv */
3177
        if (dflag) {
3178
            val = insn_get(s, OT_LONG);
3179
        } else {
3180
            val = (int16_t)insn_get(s, OT_WORD); 
3181
        }
3182
    do_jcc:
3183
        next_eip = s->pc - s->cs_base;
3184
        val += next_eip;
3185
        if (s->dflag == 0)
3186
            val &= 0xffff;
3187
        gen_jcc(s, b, val, next_eip);
3188
        break;
3189

    
3190
    case 0x190 ... 0x19f: /* setcc Gv */
3191
        modrm = ldub(s->pc++);
3192
        gen_setcc(s, b);
3193
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3194
        break;
3195
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
3196
        ot = dflag ? OT_LONG : OT_WORD;
3197
        modrm = ldub(s->pc++);
3198
        reg = (modrm >> 3) & 7;
3199
        mod = (modrm >> 6) & 3;
3200
        gen_setcc(s, b);
3201
        if (mod != 3) {
3202
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3203
            gen_op_ld_T1_A0[ot]();
3204
        } else {
3205
            rm = modrm & 7;
3206
            gen_op_mov_TN_reg[ot][1][rm]();
3207
        }
3208
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3209
        break;
3210
        
3211
        /************************/
3212
        /* flags */
3213
    case 0x9c: /* pushf */
3214
        if (s->vm86 && s->iopl != 3) {
3215
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3216
        } else {
3217
            if (s->cc_op != CC_OP_DYNAMIC)
3218
                gen_op_set_cc_op(s->cc_op);
3219
            gen_op_movl_T0_eflags();
3220
            gen_push_T0(s);
3221
        }
3222
        break;
3223
    case 0x9d: /* popf */
3224
        if (s->vm86 && s->iopl != 3) {
3225
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3226
        } else {
3227
            gen_pop_T0(s);
3228
            if (s->cpl == 0) {
3229
                if (s->dflag) {
3230
                    gen_op_movl_eflags_T0_cpl0();
3231
                } else {
3232
                    gen_op_movw_eflags_T0_cpl0();
3233
                }
3234
            } else {
3235
                if (s->dflag) {
3236
                    gen_op_movl_eflags_T0();
3237
                } else {
3238
                    gen_op_movw_eflags_T0();
3239
                }
3240
            }
3241
            gen_pop_update(s);
3242
            s->cc_op = CC_OP_EFLAGS;
3243
            s->is_jmp = 2; /* abort translation because TF flag may change */
3244
        }
3245
        break;
3246
    case 0x9e: /* sahf */
3247
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3248
        if (s->cc_op != CC_OP_DYNAMIC)
3249
            gen_op_set_cc_op(s->cc_op);
3250
        gen_op_movb_eflags_T0();
3251
        s->cc_op = CC_OP_EFLAGS;
3252
        break;
3253
    case 0x9f: /* lahf */
3254
        if (s->cc_op != CC_OP_DYNAMIC)
3255
            gen_op_set_cc_op(s->cc_op);
3256
        gen_op_movl_T0_eflags();
3257
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3258
        break;
3259
    case 0xf5: /* cmc */
3260
        if (s->cc_op != CC_OP_DYNAMIC)
3261
            gen_op_set_cc_op(s->cc_op);
3262
        gen_op_cmc();
3263
        s->cc_op = CC_OP_EFLAGS;
3264
        break;
3265
    case 0xf8: /* clc */
3266
        if (s->cc_op != CC_OP_DYNAMIC)
3267
            gen_op_set_cc_op(s->cc_op);
3268
        gen_op_clc();
3269
        s->cc_op = CC_OP_EFLAGS;
3270
        break;
3271
    case 0xf9: /* stc */
3272
        if (s->cc_op != CC_OP_DYNAMIC)
3273
            gen_op_set_cc_op(s->cc_op);
3274
        gen_op_stc();
3275
        s->cc_op = CC_OP_EFLAGS;
3276
        break;
3277
    case 0xfc: /* cld */
3278
        gen_op_cld();
3279
        break;
3280
    case 0xfd: /* std */
3281
        gen_op_std();
3282
        break;
3283

    
3284
        /************************/
3285
        /* bit operations */
3286
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
3287
        ot = dflag ? OT_LONG : OT_WORD;
3288
        modrm = ldub(s->pc++);
3289
        op = (modrm >> 3) & 7;
3290
        mod = (modrm >> 6) & 3;
3291
        rm = modrm & 7;
3292
        if (mod != 3) {
3293
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3294
            gen_op_ld_T0_A0[ot]();
3295
        } else {
3296
            gen_op_mov_TN_reg[ot][0][rm]();
3297
        }
3298
        /* load shift */
3299
        val = ldub(s->pc++);
3300
        gen_op_movl_T1_im(val);
3301
        if (op < 4)
3302
            goto illegal_op;
3303
        op -= 4;
3304
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3305
        s->cc_op = CC_OP_SARB + ot;
3306
        if (op != 0) {
3307
            if (mod != 3)
3308
                gen_op_st_T0_A0[ot]();
3309
            else
3310
                gen_op_mov_reg_T0[ot][rm]();
3311
            gen_op_update_bt_cc();
3312
        }
3313
        break;
3314
    case 0x1a3: /* bt Gv, Ev */
3315
        op = 0;
3316
        goto do_btx;
3317
    case 0x1ab: /* bts */
3318
        op = 1;
3319
        goto do_btx;
3320
    case 0x1b3: /* btr */
3321
        op = 2;
3322
        goto do_btx;
3323
    case 0x1bb: /* btc */
3324
        op = 3;
3325
    do_btx:
3326
        ot = dflag ? OT_LONG : OT_WORD;
3327
        modrm = ldub(s->pc++);
3328
        reg = (modrm >> 3) & 7;
3329
        mod = (modrm >> 6) & 3;
3330
        rm = modrm & 7;
3331
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3332
        if (mod != 3) {
3333
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3334
            /* specific case: we need to add a displacement */
3335
            if (ot == OT_WORD)
3336
                gen_op_add_bitw_A0_T1();
3337
            else
3338
                gen_op_add_bitl_A0_T1();
3339
            gen_op_ld_T0_A0[ot]();
3340
        } else {
3341
            gen_op_mov_TN_reg[ot][0][rm]();
3342
        }
3343
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3344
        s->cc_op = CC_OP_SARB + ot;
3345
        if (op != 0) {
3346
            if (mod != 3)
3347
                gen_op_st_T0_A0[ot]();
3348
            else
3349
                gen_op_mov_reg_T0[ot][rm]();
3350
            gen_op_update_bt_cc();
3351
        }
3352
        break;
3353
    case 0x1bc: /* bsf */
3354
    case 0x1bd: /* bsr */
3355
        ot = dflag ? OT_LONG : OT_WORD;
3356
        modrm = ldub(s->pc++);
3357
        reg = (modrm >> 3) & 7;
3358
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3359
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3360
        /* NOTE: we always write back the result. Intel doc says it is
3361
           undefined if T0 == 0 */
3362
        gen_op_mov_reg_T0[ot][reg]();
3363
        s->cc_op = CC_OP_LOGICB + ot;
3364
        break;
3365
        /************************/
3366
        /* bcd */
3367
    case 0x27: /* daa */
3368
        if (s->cc_op != CC_OP_DYNAMIC)
3369
            gen_op_set_cc_op(s->cc_op);
3370
        gen_op_daa();
3371
        s->cc_op = CC_OP_EFLAGS;
3372
        break;
3373
    case 0x2f: /* das */
3374
        if (s->cc_op != CC_OP_DYNAMIC)
3375
            gen_op_set_cc_op(s->cc_op);
3376
        gen_op_das();
3377
        s->cc_op = CC_OP_EFLAGS;
3378
        break;
3379
    case 0x37: /* aaa */
3380
        if (s->cc_op != CC_OP_DYNAMIC)
3381
            gen_op_set_cc_op(s->cc_op);
3382
        gen_op_aaa();
3383
        s->cc_op = CC_OP_EFLAGS;
3384
        break;
3385
    case 0x3f: /* aas */
3386
        if (s->cc_op != CC_OP_DYNAMIC)
3387
            gen_op_set_cc_op(s->cc_op);
3388
        gen_op_aas();
3389
        s->cc_op = CC_OP_EFLAGS;
3390
        break;
3391
    case 0xd4: /* aam */
3392
        val = ldub(s->pc++);
3393
        gen_op_aam(val);
3394
        s->cc_op = CC_OP_LOGICB;
3395
        break;
3396
    case 0xd5: /* aad */
3397
        val = ldub(s->pc++);
3398
        gen_op_aad(val);
3399
        s->cc_op = CC_OP_LOGICB;
3400
        break;
3401
        /************************/
3402
        /* misc */
3403
    case 0x90: /* nop */
3404
        break;
3405
    case 0x9b: /* fwait */
3406
        break;
3407
    case 0xcc: /* int3 */
3408
        gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3409
        break;
3410
    case 0xcd: /* int N */
3411
        val = ldub(s->pc++);
3412
        /* XXX: add error code for vm86 GPF */
3413
        if (!s->vm86)
3414
            gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3415
        else
3416
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
3417
        break;
3418
    case 0xce: /* into */
3419
        if (s->cc_op != CC_OP_DYNAMIC)
3420
            gen_op_set_cc_op(s->cc_op);
3421
        gen_op_into(s->pc - s->cs_base);
3422
        break;
3423
    case 0xfa: /* cli */
3424
        if (!s->vm86) {
3425
            if (s->cpl <= s->iopl) {
3426
                gen_op_cli();
3427
            } else {
3428
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3429
            }
3430
        } else {
3431
            if (s->iopl == 3) {
3432
                gen_op_cli();
3433
            } else {
3434
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3435
            }
3436
        }
3437
        break;
3438
    case 0xfb: /* sti */
3439
        if (!s->vm86) {
3440
            if (s->cpl <= s->iopl) {
3441
                gen_op_sti();
3442
                s->is_jmp = 2; /* give a chance to handle pending irqs */
3443
            } else {
3444
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3445
            }
3446
        } else {
3447
            if (s->iopl == 3) {
3448
                gen_op_sti();
3449
                s->is_jmp = 2; /* give a chance to handle pending irqs */
3450
            } else {
3451
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3452
            }
3453
        }
3454
        /* XXX: interruptions are enabled only the first insn after sti */
3455
        break;
3456
    case 0x62: /* bound */
3457
        ot = dflag ? OT_LONG : OT_WORD;
3458
        modrm = ldub(s->pc++);
3459
        reg = (modrm >> 3) & 7;
3460
        mod = (modrm >> 6) & 3;
3461
        if (mod == 3)
3462
            goto illegal_op;
3463
        gen_op_mov_reg_T0[ot][reg]();
3464
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3465
        if (ot == OT_WORD)
3466
            gen_op_boundw(pc_start - s->cs_base);
3467
        else
3468
            gen_op_boundl(pc_start - s->cs_base);
3469
        break;
3470
    case 0x1c8 ... 0x1cf: /* bswap reg */
3471
        reg = b & 7;
3472
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3473
        gen_op_bswapl_T0();
3474
        gen_op_mov_reg_T0[OT_LONG][reg]();
3475
        break;
3476
    case 0xd6: /* salc */
3477
        if (s->cc_op != CC_OP_DYNAMIC)
3478
            gen_op_set_cc_op(s->cc_op);
3479
        gen_op_salc();
3480
        break;
3481
    case 0xe0: /* loopnz */
3482
    case 0xe1: /* loopz */
3483
        if (s->cc_op != CC_OP_DYNAMIC)
3484
            gen_op_set_cc_op(s->cc_op);
3485
        /* FALL THRU */
3486
    case 0xe2: /* loop */
3487
    case 0xe3: /* jecxz */
3488
        val = (int8_t)insn_get(s, OT_BYTE);
3489
        next_eip = s->pc - s->cs_base;
3490
        val += next_eip;
3491
        if (s->dflag == 0)
3492
            val &= 0xffff;
3493
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3494
        s->is_jmp = 1;
3495
        break;
3496
    case 0x130: /* wrmsr */
3497
    case 0x132: /* rdmsr */
3498
        if (s->cpl != 0) {
3499
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3500
        } else {
3501
            if (b & 2)
3502
                gen_op_rdmsr();
3503
            else
3504
                gen_op_wrmsr();
3505
        }
3506
        break;
3507
    case 0x131: /* rdtsc */
3508
        gen_op_rdtsc();
3509
        break;
3510
    case 0x1a2: /* cpuid */
3511
        gen_op_cpuid();
3512
        break;
3513
    case 0xf4: /* hlt */
3514
        if (s->cpl != 0) {
3515
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3516
        } else {
3517
            if (s->cc_op != CC_OP_DYNAMIC)
3518
                gen_op_set_cc_op(s->cc_op);
3519
            gen_op_jmp_im(s->pc - s->cs_base);
3520
            gen_op_hlt();
3521
            s->is_jmp = 1;
3522
        }
3523
        break;
3524
    case 0x100:
3525
        modrm = ldub(s->pc++);
3526
        mod = (modrm >> 6) & 3;
3527
        op = (modrm >> 3) & 7;
3528
        switch(op) {
3529
        case 0: /* sldt */
3530
            gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3531
            ot = OT_WORD;
3532
            if (mod == 3)
3533
                ot += s->dflag;
3534
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3535
            break;
3536
        case 2: /* lldt */
3537
            if (s->cpl != 0) {
3538
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3539
            } else {
3540
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3541
                gen_op_jmp_im(pc_start - s->cs_base);
3542
                gen_op_lldt_T0();
3543
            }
3544
            break;
3545
        case 1: /* str */
3546
            gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3547
            ot = OT_WORD;
3548
            if (mod == 3)
3549
                ot += s->dflag;
3550
            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3551
            break;
3552
        case 3: /* ltr */
3553
            if (s->cpl != 0) {
3554
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3555
            } else {
3556
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3557
                gen_op_jmp_im(pc_start - s->cs_base);
3558
                gen_op_ltr_T0();
3559
            }
3560
            break;
3561
        case 4: /* verr */
3562
        case 5: /* verw */
3563
        default:
3564
            goto illegal_op;
3565
        }
3566
        break;
3567
    case 0x101:
3568
        modrm = ldub(s->pc++);
3569
        mod = (modrm >> 6) & 3;
3570
        op = (modrm >> 3) & 7;
3571
        switch(op) {
3572
        case 0: /* sgdt */
3573
        case 1: /* sidt */
3574
            if (mod == 3)
3575
                goto illegal_op;
3576
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3577
            if (op == 0)
3578
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3579
            else
3580
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3581
            gen_op_stw_T0_A0();
3582
            gen_op_addl_A0_im(2);
3583
            if (op == 0)
3584
                gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3585
            else
3586
                gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3587
            if (!s->dflag)
3588
                gen_op_andl_T0_im(0xffffff);
3589
            gen_op_stl_T0_A0();
3590
            break;
3591
        case 2: /* lgdt */
3592
        case 3: /* lidt */
3593
            if (mod == 3)
3594
                goto illegal_op;
3595
            if (s->cpl != 0) {
3596
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3597
            } else {
3598
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3599
                gen_op_lduw_T1_A0();
3600
                gen_op_addl_A0_im(2);
3601
                gen_op_ldl_T0_A0();
3602
                if (!s->dflag)
3603
                    gen_op_andl_T0_im(0xffffff);
3604
                if (op == 2) {
3605
                    gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3606
                    gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3607
                } else {
3608
                    gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3609
                    gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3610
                }
3611
            }
3612
            break;
3613
        case 4: /* smsw */
3614
            gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3615
            gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3616
            break;
3617
        case 6: /* lmsw */
3618
            if (s->cpl != 0) {
3619
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3620
            } else {
3621
                gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3622
                gen_op_lmsw_T0();
3623
            }
3624
            break;
3625
        case 7: /* invlpg */
3626
            if (s->cpl != 0) {
3627
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3628
            } else {
3629
                if (mod == 3)
3630
                    goto illegal_op;
3631
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3632
                gen_op_invlpg_A0();
3633
            }
3634
            break;
3635
        default:
3636
            goto illegal_op;
3637
        }
3638
        break;
3639
    case 0x102: /* lar */
3640
    case 0x103: /* lsl */
3641
        if (!s->pe || s->vm86)
3642
            goto illegal_op;
3643
        ot = dflag ? OT_LONG : OT_WORD;
3644
        modrm = ldub(s->pc++);
3645
        reg = (modrm >> 3) & 7;
3646
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3647
        gen_op_mov_TN_reg[ot][1][reg]();
3648
        if (s->cc_op != CC_OP_DYNAMIC)
3649
            gen_op_set_cc_op(s->cc_op);
3650
        if (b == 0x102)
3651
            gen_op_lar();
3652
        else
3653
            gen_op_lsl();
3654
        s->cc_op = CC_OP_EFLAGS;
3655
        gen_op_mov_reg_T1[ot][reg]();
3656
        break;
3657
    case 0x118:
3658
        modrm = ldub(s->pc++);
3659
        mod = (modrm >> 6) & 3;
3660
        op = (modrm >> 3) & 7;
3661
        switch(op) {
3662
        case 0: /* prefetchnta */
3663
        case 1: /* prefetchnt0 */
3664
        case 2: /* prefetchnt0 */
3665
        case 3: /* prefetchnt0 */
3666
            if (mod == 3)
3667
                goto illegal_op;
3668
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3669
            /* nothing more to do */
3670
            break;
3671
        default:
3672
            goto illegal_op;
3673
        }
3674
        break;
3675
    case 0x120: /* mov reg, crN */
3676
    case 0x122: /* mov crN, reg */
3677
        if (s->cpl != 0) {
3678
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3679
        } else {
3680
            modrm = ldub(s->pc++);
3681
            if ((modrm & 0xc0) != 0xc0)
3682
                goto illegal_op;
3683
            rm = modrm & 7;
3684
            reg = (modrm >> 3) & 7;
3685
            switch(reg) {
3686
            case 0:
3687
            case 2:
3688
            case 3:
3689
            case 4:
3690
                if (b & 2) {
3691
                    gen_op_mov_TN_reg[OT_LONG][0][rm]();
3692
                    gen_op_movl_crN_T0(reg);
3693
                    s->is_jmp = 2;
3694
                } else {
3695
                    gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3696
                    gen_op_mov_reg_T0[OT_LONG][rm]();
3697
                }
3698
                break;
3699
            default:
3700
                goto illegal_op;
3701
            }
3702
        }
3703
        break;
3704
    case 0x121: /* mov reg, drN */
3705
    case 0x123: /* mov drN, reg */
3706
        if (s->cpl != 0) {
3707
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3708
        } else {
3709
            modrm = ldub(s->pc++);
3710
            if ((modrm & 0xc0) != 0xc0)
3711
                goto illegal_op;
3712
            rm = modrm & 7;
3713
            reg = (modrm >> 3) & 7;
3714
            /* XXX: do it dynamically with CR4.DE bit */
3715
            if (reg == 4 || reg == 5)
3716
                goto illegal_op;
3717
            if (b & 2) {
3718
                gen_op_mov_TN_reg[OT_LONG][0][rm]();
3719
                gen_op_movl_drN_T0(reg);
3720
                s->is_jmp = 2;
3721
            } else {
3722
                gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3723
                gen_op_mov_reg_T0[OT_LONG][rm]();
3724
            }
3725
        }
3726
        break;
3727
    case 0x106: /* clts */
3728
        if (s->cpl != 0) {
3729
            gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3730
        } else {
3731
            gen_op_clts();
3732
        }
3733
        break;
3734
    default:
3735
        goto illegal_op;
3736
    }
3737
    /* lock generation */
3738
    if (s->prefix & PREFIX_LOCK)
3739
        gen_op_unlock();
3740
    return (long)s->pc;
3741
 illegal_op:
3742
    /* XXX: ensure that no lock was generated */
3743
    return -1;
3744
}
3745

    
3746
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3747
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3748

    
3749
/* flags read by an operation */
3750
static uint16_t opc_read_flags[NB_OPS] = { 
3751
    [INDEX_op_aas] = CC_A,
3752
    [INDEX_op_aaa] = CC_A,
3753
    [INDEX_op_das] = CC_A | CC_C,
3754
    [INDEX_op_daa] = CC_A | CC_C,
3755

    
3756
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3757
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3758
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3759
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3760
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3761
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3762

    
3763
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
3764
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
3765
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
3766
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
3767
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
3768
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
3769

    
3770
    /* subtle: due to the incl/decl implementation, C is used */
3771
    [INDEX_op_update_inc_cc] = CC_C, 
3772

    
3773
    [INDEX_op_into] = CC_O,
3774

    
3775
    [INDEX_op_jb_subb] = CC_C,
3776
    [INDEX_op_jb_subw] = CC_C,
3777
    [INDEX_op_jb_subl] = CC_C,
3778

    
3779
    [INDEX_op_jz_subb] = CC_Z,
3780
    [INDEX_op_jz_subw] = CC_Z,
3781
    [INDEX_op_jz_subl] = CC_Z,
3782

    
3783
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3784
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3785
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3786

    
3787
    [INDEX_op_js_subb] = CC_S,
3788
    [INDEX_op_js_subw] = CC_S,
3789
    [INDEX_op_js_subl] = CC_S,
3790

    
3791
    [INDEX_op_jl_subb] = CC_O | CC_S,
3792
    [INDEX_op_jl_subw] = CC_O | CC_S,
3793
    [INDEX_op_jl_subl] = CC_O | CC_S,
3794

    
3795
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3796
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3797
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3798

    
3799
    [INDEX_op_loopnzw] = CC_Z,
3800
    [INDEX_op_loopnzl] = CC_Z,
3801
    [INDEX_op_loopzw] = CC_Z,
3802
    [INDEX_op_loopzl] = CC_Z,
3803

    
3804
    [INDEX_op_seto_T0_cc] = CC_O,
3805
    [INDEX_op_setb_T0_cc] = CC_C,
3806
    [INDEX_op_setz_T0_cc] = CC_Z,
3807
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3808
    [INDEX_op_sets_T0_cc] = CC_S,
3809
    [INDEX_op_setp_T0_cc] = CC_P,
3810
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3811
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3812

    
3813
    [INDEX_op_setb_T0_subb] = CC_C,
3814
    [INDEX_op_setb_T0_subw] = CC_C,
3815
    [INDEX_op_setb_T0_subl] = CC_C,
3816

    
3817
    [INDEX_op_setz_T0_subb] = CC_Z,
3818
    [INDEX_op_setz_T0_subw] = CC_Z,
3819
    [INDEX_op_setz_T0_subl] = CC_Z,
3820

    
3821
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3822
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3823
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3824

    
3825
    [INDEX_op_sets_T0_subb] = CC_S,
3826
    [INDEX_op_sets_T0_subw] = CC_S,
3827
    [INDEX_op_sets_T0_subl] = CC_S,
3828

    
3829
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3830
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3831
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3832

    
3833
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3834
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3835
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3836

    
3837
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3838
    [INDEX_op_cmc] = CC_C,
3839
    [INDEX_op_salc] = CC_C,
3840

    
3841
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3842
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3843
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3844
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3845
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3846
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3847

    
3848
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
3849
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
3850
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
3851
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
3852
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
3853
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
3854
};
3855

    
3856
/* flags written by an operation */
3857
static uint16_t opc_write_flags[NB_OPS] = { 
3858
    [INDEX_op_update2_cc] = CC_OSZAPC,
3859
    [INDEX_op_update1_cc] = CC_OSZAPC,
3860
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3861
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
3862
    /* subtle: due to the incl/decl implementation, C is used */
3863
    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
3864
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3865

    
3866
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3867
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3868
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3869
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3870
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3871
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3872

    
3873
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
3874
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
3875
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
3876
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
3877
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
3878
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
3879

    
3880
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3881
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3882
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3883
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3884
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3885
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3886
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3887
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3888
    
3889
    /* bcd */
3890
    [INDEX_op_aam] = CC_OSZAPC,
3891
    [INDEX_op_aad] = CC_OSZAPC,
3892
    [INDEX_op_aas] = CC_OSZAPC,
3893
    [INDEX_op_aaa] = CC_OSZAPC,
3894
    [INDEX_op_das] = CC_OSZAPC,
3895
    [INDEX_op_daa] = CC_OSZAPC,
3896

    
3897
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3898
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3899
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3900
    [INDEX_op_clc] = CC_C,
3901
    [INDEX_op_stc] = CC_C,
3902
    [INDEX_op_cmc] = CC_C,
3903

    
3904
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3905
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3906
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3907
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3908
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3909
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3910

    
3911
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3912
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3913
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3914
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3915
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3916
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3917

    
3918
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3919
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3920
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3921

    
3922
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3923
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3924
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3925

    
3926
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3927
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3928
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3929

    
3930
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3931
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3932
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3933
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3934

    
3935
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3936
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3937
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3938
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3939

    
3940
    [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
3941
    [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
3942
    [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
3943
    [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
3944
    [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
3945
    [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
3946

    
3947
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
3948
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
3949
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
3950
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
3951
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
3952
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
3953

    
3954
    [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
3955
    [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
3956
    [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
3957

    
3958
    [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
3959
    [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
3960
    [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
3961

    
3962
    [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
3963
    [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
3964
    [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
3965

    
3966
    [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3967
    [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3968
    [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
3969
    [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
3970

    
3971
    [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3972
    [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3973
    [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
3974
    [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
3975

    
3976
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3977
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3978
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3979
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3980
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3981
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3982
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3983
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3984

    
3985
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3986
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3987
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3988
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3989

    
3990
#undef STRINGOP
3991
#define STRINGOP(x) \
3992
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3993
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3994
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3995
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3996
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3997
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3998
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3999
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
4000
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
4001

    
4002
    STRINGOP(scas)
4003
    STRINGOP(repz_scas)
4004
    STRINGOP(repnz_scas)
4005
    STRINGOP(cmps)
4006
    STRINGOP(repz_cmps)
4007
    STRINGOP(repnz_cmps)
4008

    
4009
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4010
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4011
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4012

    
4013
    [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4014
    [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4015
    [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4016

    
4017
    [INDEX_op_cmpxchg8b] = CC_Z,
4018
    [INDEX_op_lar] = CC_Z,
4019
    [INDEX_op_lsl] = CC_Z,
4020
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4021
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4022
};
4023

    
4024
/* simpler form of an operation if no flags need to be generated */
4025
static uint16_t opc_simpler[NB_OPS] = { 
4026
    [INDEX_op_update2_cc] = INDEX_op_nop,
4027
    [INDEX_op_update1_cc] = INDEX_op_nop,
4028
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
4029
#if 0
4030
    /* broken: CC_OP logic must be rewritten */
4031
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
4032
#endif
4033
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
4034
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
4035
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
4036

    
4037
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
4038
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
4039
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
4040

    
4041
    [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
4042
    [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
4043
    [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
4044

    
4045
    [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
4046
    [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
4047
    [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
4048

    
4049
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4050
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4051
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4052

    
4053
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4054
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4055
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4056

    
4057
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4058
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4059
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4060
};
4061

    
4062
static void optimize_flags_init(void)
4063
{
4064
    int i;
4065
    /* put default values in arrays */
4066
    for(i = 0; i < NB_OPS; i++) {
4067
        if (opc_simpler[i] == 0)
4068
            opc_simpler[i] = i;
4069
    }
4070
}
4071

    
4072
/* CPU flags computation optimization: we move backward thru the
4073
   generated code to see which flags are needed. The operation is
4074
   modified if suitable */
4075
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4076
{
4077
    uint16_t *opc_ptr;
4078
    int live_flags, write_flags, op;
4079

    
4080
    opc_ptr = opc_buf + opc_buf_len;
4081
    /* live_flags contains the flags needed by the next instructions
4082
       in the code. At the end of the bloc, we consider that all the
4083
       flags are live. */
4084
    live_flags = CC_OSZAPC;
4085
    while (opc_ptr > opc_buf) {
4086
        op = *--opc_ptr;
4087
        /* if none of the flags written by the instruction is used,
4088
           then we can try to find a simpler instruction */
4089
        write_flags = opc_write_flags[op];
4090
        if ((live_flags & write_flags) == 0) {
4091
            *opc_ptr = opc_simpler[op];
4092
        }
4093
        /* compute the live flags before the instruction */
4094
        live_flags &= ~write_flags;
4095
        live_flags |= opc_read_flags[op];
4096
    }
4097
}
4098

    
4099
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4100
   basic block 'tb'. If search_pc is TRUE, also generate PC
4101
   information for each intermediate instruction. */
4102
static inline int gen_intermediate_code_internal(CPUState *env,
4103
                                                 TranslationBlock *tb, 
4104
                                                 int search_pc)
4105
{
4106
    DisasContext dc1, *dc = &dc1;
4107
    uint8_t *pc_ptr;
4108
    uint16_t *gen_opc_end;
4109
    int flags, j, lj;
4110
    long ret;
4111
    uint8_t *pc_start;
4112
    uint8_t *cs_base;
4113
    
4114
    /* generate intermediate code */
4115
    pc_start = (uint8_t *)tb->pc;
4116
    cs_base = (uint8_t *)tb->cs_base;
4117
    flags = tb->flags;
4118
       
4119
    dc->pe = env->cr[0] & CR0_PE_MASK;
4120
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
4121
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
4122
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
4123
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
4124
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
4125
    /* CPL is implicit if real mode or vm86 mode */
4126
    if (!dc->pe)
4127
        dc->cpl = 0;
4128
    else if (dc->vm86)
4129
        dc->cpl = 3;
4130
    else
4131
        dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4132
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
4133
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
4134
    dc->cc_op = CC_OP_DYNAMIC;
4135
    dc->cs_base = cs_base;
4136
    dc->tb = tb;
4137
    dc->popl_esp_hack = 0;
4138

    
4139
    gen_opc_ptr = gen_opc_buf;
4140
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4141
    gen_opparam_ptr = gen_opparam_buf;
4142

    
4143
    dc->is_jmp = DISAS_NEXT;
4144
    pc_ptr = pc_start;
4145
    lj = -1;
4146
    do {
4147
        if (env->nb_breakpoints > 0) {
4148
            for(j = 0; j < env->nb_breakpoints; j++) {
4149
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4150
                    gen_debug(dc, pc_ptr - dc->cs_base);
4151
                    goto the_end;
4152
                }
4153
            }
4154
        }
4155
        if (search_pc) {
4156
            j = gen_opc_ptr - gen_opc_buf;
4157
            if (lj < j) {
4158
                lj++;
4159
                while (lj < j)
4160
                    gen_opc_instr_start[lj++] = 0;
4161
            }
4162
            gen_opc_pc[lj] = (uint32_t)pc_ptr;
4163
            gen_opc_cc_op[lj] = dc->cc_op;
4164
            gen_opc_instr_start[lj] = 1;
4165
        }
4166
        ret = disas_insn(dc, pc_ptr);
4167
        if (ret == -1) {
4168
            /* we trigger an illegal instruction operation only if it
4169
               is the first instruction. Otherwise, we simply stop
4170
               generating the code just before it */
4171
            if (pc_ptr == pc_start)
4172
                return -1;
4173
            else
4174
                break;
4175
        }
4176
        pc_ptr = (void *)ret;
4177
        /* if single step mode, we generate only one instruction and
4178
           generate an exception */
4179
        if (dc->tf)
4180
            break;
4181
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
4182
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4183
    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4184
        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4185
    }
4186

    
4187
    /* we must store the eflags state if it is not already done */
4188
    if (dc->is_jmp != DISAS_TB_JUMP) {
4189
        if (dc->cc_op != CC_OP_DYNAMIC)
4190
            gen_op_set_cc_op(dc->cc_op);
4191
        if (dc->is_jmp != DISAS_JUMP) {
4192
            /* we add an additionnal jmp to update the simulated PC */
4193
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4194
        }
4195
    }
4196
    if (dc->tf) {
4197
        gen_op_raise_exception(EXCP01_SSTP);
4198
    }
4199
 the_end:
4200
    if (dc->is_jmp != DISAS_TB_JUMP) {
4201
        /* indicate that the hash table must be used to find the next TB */
4202
        gen_op_movl_T0_0();
4203
        gen_op_exit_tb();
4204
    }
4205
    *gen_opc_ptr = INDEX_op_end;
4206
    /* we don't forget to fill the last values */
4207
    if (search_pc) {
4208
        j = gen_opc_ptr - gen_opc_buf;
4209
        lj++;
4210
        while (lj <= j)
4211
            gen_opc_instr_start[lj++] = 0;
4212
    }
4213
        
4214
#ifdef DEBUG_DISAS
4215
    if (loglevel) {
4216
        fprintf(logfile, "----------------\n");
4217
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4218
        disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4219
        fprintf(logfile, "\n");
4220

    
4221
        fprintf(logfile, "OP:\n");
4222
        dump_ops(gen_opc_buf, gen_opparam_buf);
4223
        fprintf(logfile, "\n");
4224
    }
4225
#endif
4226

    
4227
    /* optimize flag computations */
4228
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4229

    
4230
#ifdef DEBUG_DISAS
4231
    if (loglevel) {
4232
        fprintf(logfile, "AFTER FLAGS OPT:\n");
4233
        dump_ops(gen_opc_buf, gen_opparam_buf);
4234
        fprintf(logfile, "\n");
4235
    }
4236
#endif
4237
    if (!search_pc)
4238
        tb->size = pc_ptr - pc_start;
4239
    return 0;
4240
}
4241

    
4242
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4243
{
4244
    return gen_intermediate_code_internal(env, tb, 0);
4245
}
4246

    
4247
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4248
{
4249
    return gen_intermediate_code_internal(env, tb, 1);
4250
}
4251

    
4252
CPUX86State *cpu_x86_init(void)
4253
{
4254
    CPUX86State *env;
4255
    int i;
4256
    static int inited;
4257

    
4258
    cpu_exec_init();
4259

    
4260
    env = malloc(sizeof(CPUX86State));
4261
    if (!env)
4262
        return NULL;
4263
    memset(env, 0, sizeof(CPUX86State));
4264
    /* basic FPU init */
4265
    for(i = 0;i < 8; i++)
4266
        env->fptags[i] = 1;
4267
    env->fpuc = 0x37f;
4268
    /* flags setup : we activate the IRQs by default as in user mode */
4269
    env->eflags = 0x2 | IF_MASK;
4270

    
4271
    /* init various static tables */
4272
    if (!inited) {
4273
        inited = 1;
4274
        optimize_flags_init();
4275
    }
4276
    return env;
4277
}
4278

    
4279
void cpu_x86_close(CPUX86State *env)
4280
{
4281
    free(env);
4282
}
4283

    
4284
/***********************************************************/
4285
/* x86 mmu */
4286
/* XXX: add PGE support */
4287

    
4288
/* called when cr3 or PG bit are modified */
4289
static int last_pg_state = -1;
4290
static int last_pe_state = 0;
4291
int phys_ram_size;
4292
int phys_ram_fd;
4293
uint8_t *phys_ram_base;
4294

    
4295
void cpu_x86_update_cr0(CPUX86State *env)
4296
{
4297
    int pg_state, pe_state;
4298
    void *map_addr;
4299

    
4300
#ifdef DEBUG_MMU
4301
    printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
4302
#endif
4303
    pg_state = env->cr[0] & CR0_PG_MASK;
4304
    if (pg_state != last_pg_state) {
4305
        if (!pg_state) {
4306
            /* we map the physical memory at address 0 */
4307
            
4308
            map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ, 
4309
                            MAP_SHARED | MAP_FIXED, phys_ram_fd, 0);
4310
            if (map_addr == MAP_FAILED) {
4311
                fprintf(stderr, 
4312
                        "Could not map physical memory at host address 0x%08x\n",
4313
                        0);
4314
                exit(1);
4315
            }
4316
            page_set_flags(0, phys_ram_size, 
4317
                           PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC);
4318
        } else {
4319
            /* we unmap the physical memory */
4320
            munmap((void *)0, phys_ram_size);
4321
            page_set_flags(0, phys_ram_size, 0);
4322
        }
4323
        last_pg_state = pg_state;
4324
    }
4325
    pe_state = env->cr[0] & CR0_PE_MASK;
4326
    if (last_pe_state != pe_state) {
4327
        tb_flush();
4328
        last_pe_state = pe_state;
4329
    }
4330
}
4331

    
4332
void cpu_x86_update_cr3(CPUX86State *env)
4333
{
4334
    if (env->cr[0] & CR0_PG_MASK) {
4335
#if defined(DEBUG_MMU)
4336
        printf("CR3 update: CR3=%08x\n", env->cr[3]);
4337
#endif
4338
        page_unmap();
4339
    }
4340
}
4341

    
4342
void cpu_x86_init_mmu(CPUX86State *env)
4343
{
4344
    last_pg_state = -1;
4345
    cpu_x86_update_cr0(env);
4346
}
4347

    
4348
/* XXX: also flush 4MB pages */
4349
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
4350
{
4351
    int flags;
4352
    unsigned long virt_addr;
4353

    
4354
    flags = page_get_flags(addr);
4355
    if (flags & PAGE_VALID) {
4356
        virt_addr = addr & ~0xfff;
4357
        munmap((void *)virt_addr, 4096);
4358
        page_set_flags(virt_addr, virt_addr + 4096, 0);
4359
    }
4360
}
4361

    
4362
/* return value:
4363
   -1 = cannot handle fault 
4364
   0  = nothing more to do 
4365
   1  = generate PF fault
4366
*/
4367
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
4368
{
4369
    uint8_t *pde_ptr, *pte_ptr;
4370
    uint32_t pde, pte, virt_addr;
4371
    int cpl, error_code, is_dirty, is_user, prot, page_size;
4372
    void *map_addr;
4373

    
4374
    cpl = env->segs[R_CS].selector & 3;
4375
    is_user = (cpl == 3);
4376
    
4377
#ifdef DEBUG_MMU
4378
    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
4379
           addr, is_write, is_user, env->eip);
4380
#endif
4381

    
4382
    if (env->user_mode_only) {
4383
        /* user mode only emulation */
4384
        error_code = 0;
4385
        goto do_fault;
4386
    }
4387

    
4388
    if (!(env->cr[0] & CR0_PG_MASK))
4389
        return -1;
4390

    
4391
    /* page directory entry */
4392
    pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
4393
    pde = ldl(pde_ptr);
4394
    if (!(pde & PG_PRESENT_MASK)) {
4395
        error_code = 0;
4396
        goto do_fault;
4397
    }
4398
    if (is_user) {
4399
        if (!(pde & PG_USER_MASK))
4400
            goto do_fault_protect;
4401
        if (is_write && !(pde & PG_RW_MASK))
4402
            goto do_fault_protect;
4403
    } else {
4404
        if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
4405
            is_write && !(pde & PG_RW_MASK)) 
4406
            goto do_fault_protect;
4407
    }
4408
    /* if PSE bit is set, then we use a 4MB page */
4409
    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
4410
        is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4411
        if (!(pde & PG_ACCESSED_MASK)) {
4412
            pde |= PG_ACCESSED_MASK;
4413
            if (is_dirty)
4414
                pde |= PG_DIRTY_MASK;
4415
            stl(pde_ptr, pde);
4416
        }
4417
        
4418
        pte = pde & ~0x003ff000; /* align to 4MB */
4419
        page_size = 4096 * 1024;
4420
        virt_addr = addr & ~0x003fffff;
4421
    } else {
4422
        if (!(pde & PG_ACCESSED_MASK)) {
4423
            pde |= PG_ACCESSED_MASK;
4424
            stl(pde_ptr, pde);
4425
        }
4426

    
4427
        /* page directory entry */
4428
        pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
4429
        pte = ldl(pte_ptr);
4430
        if (!(pte & PG_PRESENT_MASK)) {
4431
            error_code = 0;
4432
            goto do_fault;
4433
        }
4434
        if (is_user) {
4435
            if (!(pte & PG_USER_MASK))
4436
                goto do_fault_protect;
4437
            if (is_write && !(pte & PG_RW_MASK))
4438
                goto do_fault_protect;
4439
        } else {
4440
            if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
4441
                is_write && !(pte & PG_RW_MASK)) 
4442
                goto do_fault_protect;
4443
        }
4444
        is_dirty = is_write && !(pte & PG_DIRTY_MASK);
4445
        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
4446
            pte |= PG_ACCESSED_MASK;
4447
            if (is_dirty)
4448
                pte |= PG_DIRTY_MASK;
4449
            stl(pte_ptr, pte);
4450
        }
4451
        page_size = 4096;
4452
        virt_addr = addr & ~0xfff;
4453
    }
4454
    /* the page can be put in the TLB */
4455
    prot = PROT_READ;
4456
    if (is_user) {
4457
        if (pte & PG_RW_MASK)
4458
            prot |= PROT_WRITE;
4459
    } else {
4460
        if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
4461
            (pte & PG_RW_MASK))
4462
            prot |= PROT_WRITE;
4463
    }
4464
    map_addr = mmap((void *)virt_addr, page_size, prot, 
4465
                    MAP_SHARED | MAP_FIXED, phys_ram_fd, pte & ~0xfff);
4466
    if (map_addr == MAP_FAILED) {
4467
        fprintf(stderr, 
4468
                "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
4469
                pte & ~0xfff, virt_addr);
4470
        exit(1);
4471
    }
4472
    page_set_flags(virt_addr, virt_addr + page_size, 
4473
                   PAGE_VALID | PAGE_EXEC | prot);
4474
#ifdef DEBUG_MMU
4475
    printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", 
4476
           pte & ~0xfff, virt_addr, (page_size != 4096));
4477
#endif
4478
    return 0;
4479
 do_fault_protect:
4480
    error_code = PG_ERROR_P_MASK;
4481
 do_fault:
4482
    env->cr[2] = addr;
4483
    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
4484
    if (is_user)
4485
        env->error_code |= PG_ERROR_U_MASK;
4486
    return 1;
4487
}
4488

    
4489
/***********************************************************/
4490
/* x86 debug */
4491

    
4492
static const char *cc_op_str[] = {
4493
    "DYNAMIC",
4494
    "EFLAGS",
4495
    "MUL",
4496
    "ADDB",
4497
    "ADDW",
4498
    "ADDL",
4499
    "ADCB",
4500
    "ADCW",
4501
    "ADCL",
4502
    "SUBB",
4503
    "SUBW",
4504
    "SUBL",
4505
    "SBBB",
4506
    "SBBW",
4507
    "SBBL",
4508
    "LOGICB",
4509
    "LOGICW",
4510
    "LOGICL",
4511
    "INCB",
4512
    "INCW",
4513
    "INCL",
4514
    "DECB",
4515
    "DECW",
4516
    "DECL",
4517
    "SHLB",
4518
    "SHLW",
4519
    "SHLL",
4520
    "SARB",
4521
    "SARW",
4522
    "SARL",
4523
};
4524

    
4525
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4526
{
4527
    int eflags;
4528
    char cc_op_name[32];
4529

    
4530
    eflags = env->eflags;
4531
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4532
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4533
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4534
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
4535
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
4536
            env->eip, eflags,
4537
            eflags & DF_MASK ? 'D' : '-',
4538
            eflags & CC_O ? 'O' : '-',
4539
            eflags & CC_S ? 'S' : '-',
4540
            eflags & CC_Z ? 'Z' : '-',
4541
            eflags & CC_A ? 'A' : '-',
4542
            eflags & CC_P ? 'P' : '-',
4543
            eflags & CC_C ? 'C' : '-');
4544
    fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4545
            env->segs[R_CS].selector,
4546
            env->segs[R_SS].selector,
4547
            env->segs[R_DS].selector,
4548
            env->segs[R_ES].selector,
4549
            env->segs[R_FS].selector,
4550
            env->segs[R_GS].selector);
4551
    if (flags & X86_DUMP_CCOP) {
4552
        if ((unsigned)env->cc_op < CC_OP_NB)
4553
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
4554
        else
4555
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4556
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4557
                env->cc_src, env->cc_dst, cc_op_name);
4558
    }
4559
    if (flags & X86_DUMP_FPU) {
4560
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
4561
                (double)env->fpregs[0], 
4562
                (double)env->fpregs[1], 
4563
                (double)env->fpregs[2], 
4564
                (double)env->fpregs[3]);
4565
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
4566
                (double)env->fpregs[4], 
4567
                (double)env->fpregs[5], 
4568
                (double)env->fpregs[7], 
4569
                (double)env->fpregs[8]);
4570
    }
4571
}