Statistics
| Branch: | Revision:

root / translate-i386.c @ b6d78bfa

History | View | Annotate | Download (127.4 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
    /* abort translation because the register may have a non zero base
1281
       or because ss32 may change */
1282
    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1283
        s->is_jmp = 2; 
1284
}
1285

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1809
        switch(op) {
1810
        case 0: /* inc Ev */
1811
            if (mod != 3)
1812
                opreg = OR_TMP0;
1813
            else
1814
                opreg = rm;
1815
            gen_inc(s, ot, opreg, 1);
1816
            break;
1817
        case 1: /* dec Ev */
1818
            if (mod != 3)
1819
                opreg = OR_TMP0;
1820
            else
1821
                opreg = rm;
1822
            gen_inc(s, ot, opreg, -1);
1823
            break;
1824
        case 2: /* call Ev */
1825
            /* XXX: optimize if memory (no and is necessary) */
1826
            if (s->dflag == 0)
1827
                gen_op_andl_T0_ffff();
1828
            gen_op_jmp_T0();
1829
            next_eip = s->pc - s->cs_base;
1830
            gen_op_movl_T0_im(next_eip);
1831
            gen_push_T0(s);
1832
            s->is_jmp = 1;
1833
            break;
1834
        case 3: /* lcall Ev */
1835
            gen_op_ld_T1_A0[ot]();
1836
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1837
            gen_op_lduw_T0_A0();
1838
        do_lcall:
1839
            if (s->pe && !s->vm86) {
1840
                if (s->cc_op != CC_OP_DYNAMIC)
1841
                    gen_op_set_cc_op(s->cc_op);
1842
                gen_op_jmp_im(pc_start - s->cs_base);
1843
                gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
1844
            } else {
1845
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
1846
            }
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
        do_ljmp:
1860
            if (s->pe && !s->vm86) {
1861
                if (s->cc_op != CC_OP_DYNAMIC)
1862
                    gen_op_set_cc_op(s->cc_op);
1863
                gen_op_jmp_im(pc_start - s->cs_base);
1864
                gen_op_ljmp_protected_T0_T1();
1865
            } else {
1866
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1867
                gen_op_movl_T0_T1();
1868
                gen_op_jmp_T0();
1869
            }
1870
            s->is_jmp = 1;
1871
            break;
1872
        case 6: /* push Ev */
1873
            gen_push_T0(s);
1874
            break;
1875
        default:
1876
            goto illegal_op;
1877
        }
1878
        break;
1879

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3126
            ot = dflag ? OT_LONG : OT_WORD;
3127
            offset = insn_get(s, ot);
3128
            selector = insn_get(s, OT_WORD);
3129
            
3130
            gen_op_movl_T0_im(selector);
3131
            gen_op_movl_T1_im(offset);
3132
        }
3133
        goto do_lcall;
3134
    case 0xe9: /* jmp */
3135
        ot = dflag ? OT_LONG : OT_WORD;
3136
        val = insn_get(s, ot);
3137
        val += s->pc - s->cs_base;
3138
        if (s->dflag == 0)
3139
            val = val & 0xffff;
3140
        gen_jmp(s, val);
3141
        break;
3142
    case 0xea: /* ljmp im */
3143
        {
3144
            unsigned int selector, offset;
3145

    
3146
            ot = dflag ? OT_LONG : OT_WORD;
3147
            offset = insn_get(s, ot);
3148
            selector = insn_get(s, OT_WORD);
3149
            
3150
            gen_op_movl_T0_im(selector);
3151
            gen_op_movl_T1_im(offset);
3152
        }
3153
        goto do_ljmp;
3154
    case 0xeb: /* jmp Jb */
3155
        val = (int8_t)insn_get(s, OT_BYTE);
3156
        val += s->pc - s->cs_base;
3157
        if (s->dflag == 0)
3158
            val = val & 0xffff;
3159
        gen_jmp(s, val);
3160
        break;
3161
    case 0x70 ... 0x7f: /* jcc Jb */
3162
        val = (int8_t)insn_get(s, OT_BYTE);
3163
        goto do_jcc;
3164
    case 0x180 ... 0x18f: /* jcc Jv */
3165
        if (dflag) {
3166
            val = insn_get(s, OT_LONG);
3167
        } else {
3168
            val = (int16_t)insn_get(s, OT_WORD); 
3169
        }
3170
    do_jcc:
3171
        next_eip = s->pc - s->cs_base;
3172
        val += next_eip;
3173
        if (s->dflag == 0)
3174
            val &= 0xffff;
3175
        gen_jcc(s, b, val, next_eip);
3176
        break;
3177

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

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

    
3737
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3738
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3739

    
3740
/* flags read by an operation */
3741
static uint16_t opc_read_flags[NB_OPS] = { 
3742
    [INDEX_op_aas] = CC_A,
3743
    [INDEX_op_aaa] = CC_A,
3744
    [INDEX_op_das] = CC_A | CC_C,
3745
    [INDEX_op_daa] = CC_A | CC_C,
3746

    
3747
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3748
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3749
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3750
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3751
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3752
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3753

    
3754
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
3755
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
3756
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
3757
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
3758
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
3759
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
3760

    
3761
    /* subtle: due to the incl/decl implementation, C is used */
3762
    [INDEX_op_update_inc_cc] = CC_C, 
3763

    
3764
    [INDEX_op_into] = CC_O,
3765

    
3766
    [INDEX_op_jb_subb] = CC_C,
3767
    [INDEX_op_jb_subw] = CC_C,
3768
    [INDEX_op_jb_subl] = CC_C,
3769

    
3770
    [INDEX_op_jz_subb] = CC_Z,
3771
    [INDEX_op_jz_subw] = CC_Z,
3772
    [INDEX_op_jz_subl] = CC_Z,
3773

    
3774
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3775
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3776
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3777

    
3778
    [INDEX_op_js_subb] = CC_S,
3779
    [INDEX_op_js_subw] = CC_S,
3780
    [INDEX_op_js_subl] = CC_S,
3781

    
3782
    [INDEX_op_jl_subb] = CC_O | CC_S,
3783
    [INDEX_op_jl_subw] = CC_O | CC_S,
3784
    [INDEX_op_jl_subl] = CC_O | CC_S,
3785

    
3786
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3787
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3788
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3789

    
3790
    [INDEX_op_loopnzw] = CC_Z,
3791
    [INDEX_op_loopnzl] = CC_Z,
3792
    [INDEX_op_loopzw] = CC_Z,
3793
    [INDEX_op_loopzl] = CC_Z,
3794

    
3795
    [INDEX_op_seto_T0_cc] = CC_O,
3796
    [INDEX_op_setb_T0_cc] = CC_C,
3797
    [INDEX_op_setz_T0_cc] = CC_Z,
3798
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3799
    [INDEX_op_sets_T0_cc] = CC_S,
3800
    [INDEX_op_setp_T0_cc] = CC_P,
3801
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3802
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3803

    
3804
    [INDEX_op_setb_T0_subb] = CC_C,
3805
    [INDEX_op_setb_T0_subw] = CC_C,
3806
    [INDEX_op_setb_T0_subl] = CC_C,
3807

    
3808
    [INDEX_op_setz_T0_subb] = CC_Z,
3809
    [INDEX_op_setz_T0_subw] = CC_Z,
3810
    [INDEX_op_setz_T0_subl] = CC_Z,
3811

    
3812
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3813
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3814
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3815

    
3816
    [INDEX_op_sets_T0_subb] = CC_S,
3817
    [INDEX_op_sets_T0_subw] = CC_S,
3818
    [INDEX_op_sets_T0_subl] = CC_S,
3819

    
3820
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3821
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3822
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3823

    
3824
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3825
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3826
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3827

    
3828
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3829
    [INDEX_op_cmc] = CC_C,
3830
    [INDEX_op_salc] = CC_C,
3831

    
3832
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3833
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3834
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3835
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3836
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3837
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3838

    
3839
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
3840
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
3841
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
3842
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
3843
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
3844
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
3845
};
3846

    
3847
/* flags written by an operation */
3848
static uint16_t opc_write_flags[NB_OPS] = { 
3849
    [INDEX_op_update2_cc] = CC_OSZAPC,
3850
    [INDEX_op_update1_cc] = CC_OSZAPC,
3851
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3852
    [INDEX_op_update_neg_cc] = CC_OSZAPC,
3853
    /* subtle: due to the incl/decl implementation, C is used */
3854
    [INDEX_op_update_inc_cc] = CC_OSZAPC, 
3855
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3856

    
3857
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3858
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3859
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3860
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3861
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3862
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3863

    
3864
    [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
3865
    [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
3866
    [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
3867
    [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
3868
    [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
3869
    [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
3870

    
3871
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3872
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3873
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3874
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3875
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3876
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3877
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3878
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3879
    
3880
    /* bcd */
3881
    [INDEX_op_aam] = CC_OSZAPC,
3882
    [INDEX_op_aad] = CC_OSZAPC,
3883
    [INDEX_op_aas] = CC_OSZAPC,
3884
    [INDEX_op_aaa] = CC_OSZAPC,
3885
    [INDEX_op_das] = CC_OSZAPC,
3886
    [INDEX_op_daa] = CC_OSZAPC,
3887

    
3888
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3889
    [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3890
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3891
    [INDEX_op_clc] = CC_C,
3892
    [INDEX_op_stc] = CC_C,
3893
    [INDEX_op_cmc] = CC_C,
3894

    
3895
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3896
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3897
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3898
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3899
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3900
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3901

    
3902
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3903
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3904
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3905
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3906
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3907
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3908

    
3909
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3910
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3911
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3912

    
3913
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3914
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3915
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3916

    
3917
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3918
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3919
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3920

    
3921
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3922
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3923
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3924
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3925

    
3926
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3927
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3928
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3929
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3930

    
3931
    [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
3932
    [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
3933
    [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
3934
    [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
3935
    [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
3936
    [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
3937

    
3938
    [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
3939
    [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
3940
    [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
3941
    [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
3942
    [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
3943
    [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
3944

    
3945
    [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
3946
    [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
3947
    [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
3948

    
3949
    [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
3950
    [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
3951
    [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
3952

    
3953
    [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
3954
    [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
3955
    [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
3956

    
3957
    [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3958
    [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3959
    [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
3960
    [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
3961

    
3962
    [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3963
    [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3964
    [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
3965
    [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
3966

    
3967
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3968
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3969
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3970
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3971
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3972
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3973
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3974
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3975

    
3976
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3977
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3978
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3979
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3980

    
3981
#undef STRINGOP
3982
#define STRINGOP(x) \
3983
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3984
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3985
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3986
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3987
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3988
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3989
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3990
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3991
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3992

    
3993
    STRINGOP(scas)
3994
    STRINGOP(repz_scas)
3995
    STRINGOP(repnz_scas)
3996
    STRINGOP(cmps)
3997
    STRINGOP(repz_cmps)
3998
    STRINGOP(repnz_cmps)
3999

    
4000
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4001
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4002
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4003

    
4004
    [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4005
    [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4006
    [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4007

    
4008
    [INDEX_op_cmpxchg8b] = CC_Z,
4009
    [INDEX_op_lar] = CC_Z,
4010
    [INDEX_op_lsl] = CC_Z,
4011
    [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4012
    [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4013
};
4014

    
4015
/* simpler form of an operation if no flags need to be generated */
4016
static uint16_t opc_simpler[NB_OPS] = { 
4017
    [INDEX_op_update2_cc] = INDEX_op_nop,
4018
    [INDEX_op_update1_cc] = INDEX_op_nop,
4019
    [INDEX_op_update_neg_cc] = INDEX_op_nop,
4020
#if 0
4021
    /* broken: CC_OP logic must be rewritten */
4022
    [INDEX_op_update_inc_cc] = INDEX_op_nop,
4023
#endif
4024
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
4025
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
4026
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
4027

    
4028
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
4029
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
4030
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
4031

    
4032
    [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
4033
    [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
4034
    [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
4035

    
4036
    [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
4037
    [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
4038
    [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
4039

    
4040
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4041
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4042
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4043

    
4044
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4045
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4046
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4047

    
4048
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4049
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4050
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4051
};
4052

    
4053
static void optimize_flags_init(void)
4054
{
4055
    int i;
4056
    /* put default values in arrays */
4057
    for(i = 0; i < NB_OPS; i++) {
4058
        if (opc_simpler[i] == 0)
4059
            opc_simpler[i] = i;
4060
    }
4061
}
4062

    
4063
/* CPU flags computation optimization: we move backward thru the
4064
   generated code to see which flags are needed. The operation is
4065
   modified if suitable */
4066
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4067
{
4068
    uint16_t *opc_ptr;
4069
    int live_flags, write_flags, op;
4070

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

    
4090
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4091
   basic block 'tb'. If search_pc is TRUE, also generate PC
4092
   information for each intermediate instruction. */
4093
static inline int gen_intermediate_code_internal(CPUState *env,
4094
                                                 TranslationBlock *tb, 
4095
                                                 int search_pc)
4096
{
4097
    DisasContext dc1, *dc = &dc1;
4098
    uint8_t *pc_ptr;
4099
    uint16_t *gen_opc_end;
4100
    int flags, j, lj;
4101
    long ret;
4102
    uint8_t *pc_start;
4103
    uint8_t *cs_base;
4104
    
4105
    /* generate intermediate code */
4106
    pc_start = (uint8_t *)tb->pc;
4107
    cs_base = (uint8_t *)tb->cs_base;
4108
    flags = tb->flags;
4109
       
4110
    dc->pe = env->cr[0] & CR0_PE_MASK;
4111
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
4112
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
4113
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
4114
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
4115
    dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
4116
    dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4117
    dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
4118
    dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
4119
    dc->cc_op = CC_OP_DYNAMIC;
4120
    dc->cs_base = cs_base;
4121
    dc->tb = tb;
4122
    dc->popl_esp_hack = 0;
4123

    
4124
    gen_opc_ptr = gen_opc_buf;
4125
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4126
    gen_opparam_ptr = gen_opparam_buf;
4127

    
4128
    dc->is_jmp = DISAS_NEXT;
4129
    pc_ptr = pc_start;
4130
    lj = -1;
4131
    do {
4132
        if (env->nb_breakpoints > 0) {
4133
            for(j = 0; j < env->nb_breakpoints; j++) {
4134
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4135
                    gen_debug(dc, pc_ptr - dc->cs_base);
4136
                    goto the_end;
4137
                }
4138
            }
4139
        }
4140
        if (search_pc) {
4141
            j = gen_opc_ptr - gen_opc_buf;
4142
            if (lj < j) {
4143
                lj++;
4144
                while (lj < j)
4145
                    gen_opc_instr_start[lj++] = 0;
4146
            }
4147
            gen_opc_pc[lj] = (uint32_t)pc_ptr;
4148
            gen_opc_cc_op[lj] = dc->cc_op;
4149
            gen_opc_instr_start[lj] = 1;
4150
        }
4151
        ret = disas_insn(dc, pc_ptr);
4152
        if (ret == -1) {
4153
            /* we trigger an illegal instruction operation only if it
4154
               is the first instruction. Otherwise, we simply stop
4155
               generating the code just before it */
4156
            if (pc_ptr == pc_start)
4157
                return -1;
4158
            else
4159
                break;
4160
        }
4161
        pc_ptr = (void *)ret;
4162
        /* if single step mode, we generate only one instruction and
4163
           generate an exception */
4164
        if (dc->tf)
4165
            break;
4166
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
4167
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4168
    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4169
        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4170
    }
4171

    
4172
    /* we must store the eflags state if it is not already done */
4173
    if (dc->is_jmp != DISAS_TB_JUMP) {
4174
        if (dc->cc_op != CC_OP_DYNAMIC)
4175
            gen_op_set_cc_op(dc->cc_op);
4176
        if (dc->is_jmp != DISAS_JUMP) {
4177
            /* we add an additionnal jmp to update the simulated PC */
4178
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4179
        }
4180
    }
4181
    if (dc->tf) {
4182
        gen_op_raise_exception(EXCP01_SSTP);
4183
    }
4184
 the_end:
4185
    if (dc->is_jmp != DISAS_TB_JUMP) {
4186
        /* indicate that the hash table must be used to find the next TB */
4187
        gen_op_movl_T0_0();
4188
        gen_op_exit_tb();
4189
    }
4190
    *gen_opc_ptr = INDEX_op_end;
4191
    /* we don't forget to fill the last values */
4192
    if (search_pc) {
4193
        j = gen_opc_ptr - gen_opc_buf;
4194
        lj++;
4195
        while (lj <= j)
4196
            gen_opc_instr_start[lj++] = 0;
4197
    }
4198
        
4199
#ifdef DEBUG_DISAS
4200
    if (loglevel) {
4201
        fprintf(logfile, "----------------\n");
4202
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4203
        disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4204
        fprintf(logfile, "\n");
4205

    
4206
        fprintf(logfile, "OP:\n");
4207
        dump_ops(gen_opc_buf, gen_opparam_buf);
4208
        fprintf(logfile, "\n");
4209
    }
4210
#endif
4211

    
4212
    /* optimize flag computations */
4213
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4214

    
4215
#ifdef DEBUG_DISAS
4216
    if (loglevel) {
4217
        fprintf(logfile, "AFTER FLAGS OPT:\n");
4218
        dump_ops(gen_opc_buf, gen_opparam_buf);
4219
        fprintf(logfile, "\n");
4220
    }
4221
#endif
4222
    if (!search_pc)
4223
        tb->size = pc_ptr - pc_start;
4224
    return 0;
4225
}
4226

    
4227
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4228
{
4229
    return gen_intermediate_code_internal(env, tb, 0);
4230
}
4231

    
4232
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4233
{
4234
    return gen_intermediate_code_internal(env, tb, 1);
4235
}
4236

    
4237
CPUX86State *cpu_x86_init(void)
4238
{
4239
    CPUX86State *env;
4240
    int i;
4241
    static int inited;
4242

    
4243
    cpu_exec_init();
4244

    
4245
    env = malloc(sizeof(CPUX86State));
4246
    if (!env)
4247
        return NULL;
4248
    memset(env, 0, sizeof(CPUX86State));
4249
    /* basic FPU init */
4250
    for(i = 0;i < 8; i++)
4251
        env->fptags[i] = 1;
4252
    env->fpuc = 0x37f;
4253
    /* flags setup : we activate the IRQs by default as in user mode */
4254
    env->eflags = 0x2 | IF_MASK;
4255

    
4256
    /* init various static tables */
4257
    if (!inited) {
4258
        inited = 1;
4259
        optimize_flags_init();
4260
    }
4261
    return env;
4262
}
4263

    
4264
void cpu_x86_close(CPUX86State *env)
4265
{
4266
    free(env);
4267
}
4268

    
4269
/***********************************************************/
4270
/* x86 mmu */
4271
/* XXX: add PGE support */
4272

    
4273
/* called when cr3 or PG bit are modified */
4274
static int last_pg_state = -1;
4275
static int last_pe_state = 0;
4276
int phys_ram_size;
4277
int phys_ram_fd;
4278
uint8_t *phys_ram_base;
4279

    
4280
void cpu_x86_update_cr0(CPUX86State *env)
4281
{
4282
    int pg_state, pe_state;
4283
    void *map_addr;
4284

    
4285
#ifdef DEBUG_MMU
4286
    printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
4287
#endif
4288
    pg_state = env->cr[0] & CR0_PG_MASK;
4289
    if (pg_state != last_pg_state) {
4290
        if (!pg_state) {
4291
            /* we map the physical memory at address 0 */
4292
            
4293
            map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ, 
4294
                            MAP_SHARED | MAP_FIXED, phys_ram_fd, 0);
4295
            if (map_addr == MAP_FAILED) {
4296
                fprintf(stderr, 
4297
                        "Could not map physical memory at host address 0x%08x\n",
4298
                        0);
4299
                exit(1);
4300
            }
4301
            page_set_flags(0, phys_ram_size, 
4302
                           PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC);
4303
        } else {
4304
            /* we unmap the physical memory */
4305
            munmap((void *)0, phys_ram_size);
4306
            page_set_flags(0, phys_ram_size, 0);
4307
        }
4308
        last_pg_state = pg_state;
4309
    }
4310
    pe_state = env->cr[0] & CR0_PE_MASK;
4311
    if (last_pe_state != pe_state) {
4312
        tb_flush();
4313
        last_pe_state = pe_state;
4314
    }
4315
}
4316

    
4317
void cpu_x86_update_cr3(CPUX86State *env)
4318
{
4319
    if (env->cr[0] & CR0_PG_MASK) {
4320
#if defined(DEBUG_MMU)
4321
        printf("CR3 update: CR3=%08x\n", env->cr[3]);
4322
#endif
4323
        page_unmap();
4324
    }
4325
}
4326

    
4327
void cpu_x86_init_mmu(CPUX86State *env)
4328
{
4329
    last_pg_state = -1;
4330
    cpu_x86_update_cr0(env);
4331
}
4332

    
4333
/* XXX: also flush 4MB pages */
4334
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
4335
{
4336
    int flags;
4337
    unsigned long virt_addr;
4338

    
4339
    flags = page_get_flags(addr);
4340
    if (flags & PAGE_VALID) {
4341
        virt_addr = addr & ~0xfff;
4342
        munmap((void *)virt_addr, 4096);
4343
        page_set_flags(virt_addr, virt_addr + 4096, 0);
4344
    }
4345
}
4346

    
4347
/* return value:
4348
   -1 = cannot handle fault 
4349
   0  = nothing more to do 
4350
   1  = generate PF fault
4351
*/
4352
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
4353
{
4354
    uint8_t *pde_ptr, *pte_ptr;
4355
    uint32_t pde, pte, virt_addr;
4356
    int cpl, error_code, is_dirty, is_user, prot, page_size;
4357
    void *map_addr;
4358

    
4359
    cpl = env->cpl;
4360
    is_user = (cpl == 3);
4361
    
4362
#ifdef DEBUG_MMU
4363
    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
4364
           addr, is_write, is_user, env->eip);
4365
#endif
4366

    
4367
    if (env->user_mode_only) {
4368
        /* user mode only emulation */
4369
        error_code = 0;
4370
        goto do_fault;
4371
    }
4372

    
4373
    if (!(env->cr[0] & CR0_PG_MASK))
4374
        return -1;
4375

    
4376
    /* page directory entry */
4377
    pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
4378
    pde = ldl(pde_ptr);
4379
    if (!(pde & PG_PRESENT_MASK)) {
4380
        error_code = 0;
4381
        goto do_fault;
4382
    }
4383
    if (is_user) {
4384
        if (!(pde & PG_USER_MASK))
4385
            goto do_fault_protect;
4386
        if (is_write && !(pde & PG_RW_MASK))
4387
            goto do_fault_protect;
4388
    } else {
4389
        if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
4390
            is_write && !(pde & PG_RW_MASK)) 
4391
            goto do_fault_protect;
4392
    }
4393
    /* if PSE bit is set, then we use a 4MB page */
4394
    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
4395
        is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4396
        if (!(pde & PG_ACCESSED_MASK)) {
4397
            pde |= PG_ACCESSED_MASK;
4398
            if (is_dirty)
4399
                pde |= PG_DIRTY_MASK;
4400
            stl(pde_ptr, pde);
4401
        }
4402
        
4403
        pte = pde & ~0x003ff000; /* align to 4MB */
4404
        page_size = 4096 * 1024;
4405
        virt_addr = addr & ~0x003fffff;
4406
    } else {
4407
        if (!(pde & PG_ACCESSED_MASK)) {
4408
            pde |= PG_ACCESSED_MASK;
4409
            stl(pde_ptr, pde);
4410
        }
4411

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

    
4474
/***********************************************************/
4475
/* x86 debug */
4476

    
4477
static const char *cc_op_str[] = {
4478
    "DYNAMIC",
4479
    "EFLAGS",
4480
    "MUL",
4481
    "ADDB",
4482
    "ADDW",
4483
    "ADDL",
4484
    "ADCB",
4485
    "ADCW",
4486
    "ADCL",
4487
    "SUBB",
4488
    "SUBW",
4489
    "SUBL",
4490
    "SBBB",
4491
    "SBBW",
4492
    "SBBL",
4493
    "LOGICB",
4494
    "LOGICW",
4495
    "LOGICL",
4496
    "INCB",
4497
    "INCW",
4498
    "INCL",
4499
    "DECB",
4500
    "DECW",
4501
    "DECL",
4502
    "SHLB",
4503
    "SHLW",
4504
    "SHLL",
4505
    "SARB",
4506
    "SARW",
4507
    "SARL",
4508
};
4509

    
4510
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4511
{
4512
    int eflags;
4513
    char cc_op_name[32];
4514

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