Statistics
| Branch: | Revision:

root / translate-i386.c @ 3ef693a0

History | View | Annotate | Download (98.1 kB)

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

    
28
#define DEBUG_DISAS
29

    
30
#define IN_OP_I386
31
#include "cpu-i386.h"
32

    
33
/* dump all code */
34
#ifdef DEBUG_DISAS
35
#include "dis-asm.h"
36
#endif
37

    
38
#ifndef offsetof
39
#define offsetof(type, field) ((size_t) &((type *)0)->field)
40
#endif
41

    
42
/* XXX: move that elsewhere */
43
static uint16_t *gen_opc_ptr;
44
static uint32_t *gen_opparam_ptr;
45
int __op_param1, __op_param2, __op_param3;
46

    
47
#ifdef __i386__
48
static inline void flush_icache_range(unsigned long start, unsigned long stop)
49
{
50
}
51
#endif
52

    
53
#ifdef __powerpc__
54

    
55
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
56

    
57
static void inline flush_icache_range(unsigned long start, unsigned long stop)
58
{
59
    unsigned long p;
60

    
61
    p = start & ~(MIN_CACHE_LINE_SIZE - 1);
62
    stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
63
    
64
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
65
        asm ("dcbst 0,%0;" : : "r"(p) : "memory");
66
    }
67
    asm ("sync");
68
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
69
        asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
70
    }
71
    asm ("sync");
72
    asm ("isync");
73
}
74
#endif
75

    
76
extern FILE *logfile;
77
extern int loglevel;
78

    
79
#define PREFIX_REPZ 1
80
#define PREFIX_REPNZ 2
81
#define PREFIX_LOCK 4
82
#define PREFIX_CS 8
83
#define PREFIX_SS 0x10
84
#define PREFIX_DS 0x20
85
#define PREFIX_ES 0x40
86
#define PREFIX_FS 0x80
87
#define PREFIX_GS 0x100
88
#define PREFIX_DATA 0x200
89
#define PREFIX_ADR 0x400
90
#define PREFIX_FWAIT 0x800
91

    
92
typedef struct DisasContext {
93
    /* current insn context */
94
    int prefix;
95
    int aflag, dflag;
96
    uint8_t *pc; /* pc = eip + cs_base */
97
    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
98
                   static state change (stop translation) */
99
    /* current block context */
100
    uint8_t *cs_base; /* base of CS segment */
101
    int code32; /* 32 bit code segment */
102
    int ss32;   /* 32 bit stack segment */
103
    int cc_op;  /* current CC operation */
104
    int addseg; /* non zero if either DS/ES/SS have a non zero base */
105
    int f_st;   /* currently unused */
106
} DisasContext;
107

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

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

    
132
enum {
133
#define DEF(s) INDEX_op_ ## s,
134
#include "opc-i386.h"
135
#undef DEF
136
    NB_OPS,
137
};
138

    
139
#include "op-i386.h"
140

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

    
149
enum {
150
    /* I386 int registers */
151
    OR_EAX,   /* MUST be even numbered */
152
    OR_ECX,
153
    OR_EDX,
154
    OR_EBX,
155
    OR_ESP,
156
    OR_EBP,
157
    OR_ESI,
158
    OR_EDI,
159
    OR_TMP0,    /* temporary operand register */
160
    OR_TMP1,
161
    OR_A0, /* temporary register used when doing address evaluation */
162
    OR_ZERO, /* fixed zero register */
163
    NB_OREGS,
164
};
165

    
166
typedef void (GenOpFunc)(void);
167
typedef void (GenOpFunc1)(long);
168
typedef void (GenOpFunc2)(long, long);
169
                    
170
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
171
    [OT_BYTE] = {
172
        gen_op_movb_EAX_T0,
173
        gen_op_movb_ECX_T0,
174
        gen_op_movb_EDX_T0,
175
        gen_op_movb_EBX_T0,
176
        gen_op_movh_EAX_T0,
177
        gen_op_movh_ECX_T0,
178
        gen_op_movh_EDX_T0,
179
        gen_op_movh_EBX_T0,
180
    },
181
    [OT_WORD] = {
182
        gen_op_movw_EAX_T0,
183
        gen_op_movw_ECX_T0,
184
        gen_op_movw_EDX_T0,
185
        gen_op_movw_EBX_T0,
186
        gen_op_movw_ESP_T0,
187
        gen_op_movw_EBP_T0,
188
        gen_op_movw_ESI_T0,
189
        gen_op_movw_EDI_T0,
190
    },
191
    [OT_LONG] = {
192
        gen_op_movl_EAX_T0,
193
        gen_op_movl_ECX_T0,
194
        gen_op_movl_EDX_T0,
195
        gen_op_movl_EBX_T0,
196
        gen_op_movl_ESP_T0,
197
        gen_op_movl_EBP_T0,
198
        gen_op_movl_ESI_T0,
199
        gen_op_movl_EDI_T0,
200
    },
201
};
202

    
203
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
204
    [OT_BYTE] = {
205
        gen_op_movb_EAX_T1,
206
        gen_op_movb_ECX_T1,
207
        gen_op_movb_EDX_T1,
208
        gen_op_movb_EBX_T1,
209
        gen_op_movh_EAX_T1,
210
        gen_op_movh_ECX_T1,
211
        gen_op_movh_EDX_T1,
212
        gen_op_movh_EBX_T1,
213
    },
214
    [OT_WORD] = {
215
        gen_op_movw_EAX_T1,
216
        gen_op_movw_ECX_T1,
217
        gen_op_movw_EDX_T1,
218
        gen_op_movw_EBX_T1,
219
        gen_op_movw_ESP_T1,
220
        gen_op_movw_EBP_T1,
221
        gen_op_movw_ESI_T1,
222
        gen_op_movw_EDI_T1,
223
    },
224
    [OT_LONG] = {
225
        gen_op_movl_EAX_T1,
226
        gen_op_movl_ECX_T1,
227
        gen_op_movl_EDX_T1,
228
        gen_op_movl_EBX_T1,
229
        gen_op_movl_ESP_T1,
230
        gen_op_movl_EBP_T1,
231
        gen_op_movl_ESI_T1,
232
        gen_op_movl_EDI_T1,
233
    },
234
};
235

    
236
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
237
    [0] = {
238
        gen_op_movw_EAX_A0,
239
        gen_op_movw_ECX_A0,
240
        gen_op_movw_EDX_A0,
241
        gen_op_movw_EBX_A0,
242
        gen_op_movw_ESP_A0,
243
        gen_op_movw_EBP_A0,
244
        gen_op_movw_ESI_A0,
245
        gen_op_movw_EDI_A0,
246
    },
247
    [1] = {
248
        gen_op_movl_EAX_A0,
249
        gen_op_movl_ECX_A0,
250
        gen_op_movl_EDX_A0,
251
        gen_op_movl_EBX_A0,
252
        gen_op_movl_ESP_A0,
253
        gen_op_movl_EBP_A0,
254
        gen_op_movl_ESI_A0,
255
        gen_op_movl_EDI_A0,
256
    },
257
};
258

    
259
static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
260
{
261
    [OT_BYTE] = {
262
        {
263
            gen_op_movl_T0_EAX,
264
            gen_op_movl_T0_ECX,
265
            gen_op_movl_T0_EDX,
266
            gen_op_movl_T0_EBX,
267
            gen_op_movh_T0_EAX,
268
            gen_op_movh_T0_ECX,
269
            gen_op_movh_T0_EDX,
270
            gen_op_movh_T0_EBX,
271
        },
272
        {
273
            gen_op_movl_T1_EAX,
274
            gen_op_movl_T1_ECX,
275
            gen_op_movl_T1_EDX,
276
            gen_op_movl_T1_EBX,
277
            gen_op_movh_T1_EAX,
278
            gen_op_movh_T1_ECX,
279
            gen_op_movh_T1_EDX,
280
            gen_op_movh_T1_EBX,
281
        },
282
    },
283
    [OT_WORD] = {
284
        {
285
            gen_op_movl_T0_EAX,
286
            gen_op_movl_T0_ECX,
287
            gen_op_movl_T0_EDX,
288
            gen_op_movl_T0_EBX,
289
            gen_op_movl_T0_ESP,
290
            gen_op_movl_T0_EBP,
291
            gen_op_movl_T0_ESI,
292
            gen_op_movl_T0_EDI,
293
        },
294
        {
295
            gen_op_movl_T1_EAX,
296
            gen_op_movl_T1_ECX,
297
            gen_op_movl_T1_EDX,
298
            gen_op_movl_T1_EBX,
299
            gen_op_movl_T1_ESP,
300
            gen_op_movl_T1_EBP,
301
            gen_op_movl_T1_ESI,
302
            gen_op_movl_T1_EDI,
303
        },
304
    },
305
    [OT_LONG] = {
306
        {
307
            gen_op_movl_T0_EAX,
308
            gen_op_movl_T0_ECX,
309
            gen_op_movl_T0_EDX,
310
            gen_op_movl_T0_EBX,
311
            gen_op_movl_T0_ESP,
312
            gen_op_movl_T0_EBP,
313
            gen_op_movl_T0_ESI,
314
            gen_op_movl_T0_EDI,
315
        },
316
        {
317
            gen_op_movl_T1_EAX,
318
            gen_op_movl_T1_ECX,
319
            gen_op_movl_T1_EDX,
320
            gen_op_movl_T1_EBX,
321
            gen_op_movl_T1_ESP,
322
            gen_op_movl_T1_EBP,
323
            gen_op_movl_T1_ESI,
324
            gen_op_movl_T1_EDI,
325
        },
326
    },
327
};
328

    
329
static GenOpFunc *gen_op_movl_A0_reg[8] = {
330
    gen_op_movl_A0_EAX,
331
    gen_op_movl_A0_ECX,
332
    gen_op_movl_A0_EDX,
333
    gen_op_movl_A0_EBX,
334
    gen_op_movl_A0_ESP,
335
    gen_op_movl_A0_EBP,
336
    gen_op_movl_A0_ESI,
337
    gen_op_movl_A0_EDI,
338
};
339

    
340
static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
341
    [0] = {
342
        gen_op_addl_A0_EAX,
343
        gen_op_addl_A0_ECX,
344
        gen_op_addl_A0_EDX,
345
        gen_op_addl_A0_EBX,
346
        gen_op_addl_A0_ESP,
347
        gen_op_addl_A0_EBP,
348
        gen_op_addl_A0_ESI,
349
        gen_op_addl_A0_EDI,
350
    },
351
    [1] = {
352
        gen_op_addl_A0_EAX_s1,
353
        gen_op_addl_A0_ECX_s1,
354
        gen_op_addl_A0_EDX_s1,
355
        gen_op_addl_A0_EBX_s1,
356
        gen_op_addl_A0_ESP_s1,
357
        gen_op_addl_A0_EBP_s1,
358
        gen_op_addl_A0_ESI_s1,
359
        gen_op_addl_A0_EDI_s1,
360
    },
361
    [2] = {
362
        gen_op_addl_A0_EAX_s2,
363
        gen_op_addl_A0_ECX_s2,
364
        gen_op_addl_A0_EDX_s2,
365
        gen_op_addl_A0_EBX_s2,
366
        gen_op_addl_A0_ESP_s2,
367
        gen_op_addl_A0_EBP_s2,
368
        gen_op_addl_A0_ESI_s2,
369
        gen_op_addl_A0_EDI_s2,
370
    },
371
    [3] = {
372
        gen_op_addl_A0_EAX_s3,
373
        gen_op_addl_A0_ECX_s3,
374
        gen_op_addl_A0_EDX_s3,
375
        gen_op_addl_A0_EBX_s3,
376
        gen_op_addl_A0_ESP_s3,
377
        gen_op_addl_A0_EBP_s3,
378
        gen_op_addl_A0_ESI_s3,
379
        gen_op_addl_A0_EDI_s3,
380
    },
381
};
382

    
383
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
384
    [0] = {
385
        gen_op_cmovw_EAX_T1_T0,
386
        gen_op_cmovw_ECX_T1_T0,
387
        gen_op_cmovw_EDX_T1_T0,
388
        gen_op_cmovw_EBX_T1_T0,
389
        gen_op_cmovw_ESP_T1_T0,
390
        gen_op_cmovw_EBP_T1_T0,
391
        gen_op_cmovw_ESI_T1_T0,
392
        gen_op_cmovw_EDI_T1_T0,
393
    },
394
    [1] = {
395
        gen_op_cmovl_EAX_T1_T0,
396
        gen_op_cmovl_ECX_T1_T0,
397
        gen_op_cmovl_EDX_T1_T0,
398
        gen_op_cmovl_EBX_T1_T0,
399
        gen_op_cmovl_ESP_T1_T0,
400
        gen_op_cmovl_EBP_T1_T0,
401
        gen_op_cmovl_ESI_T1_T0,
402
        gen_op_cmovl_EDI_T1_T0,
403
    },
404
};
405

    
406
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
407
    gen_op_addl_T0_T1_cc,
408
    gen_op_orl_T0_T1_cc,
409
    NULL,
410
    NULL,
411
    gen_op_andl_T0_T1_cc,
412
    gen_op_subl_T0_T1_cc,
413
    gen_op_xorl_T0_T1_cc,
414
    gen_op_cmpl_T0_T1_cc,
415
};
416

    
417
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
418
    [OT_BYTE] = {
419
        gen_op_adcb_T0_T1_cc,
420
        gen_op_sbbb_T0_T1_cc,
421
    },
422
    [OT_WORD] = {
423
        gen_op_adcw_T0_T1_cc,
424
        gen_op_sbbw_T0_T1_cc,
425
    },
426
    [OT_LONG] = {
427
        gen_op_adcl_T0_T1_cc,
428
        gen_op_sbbl_T0_T1_cc,
429
    },
430
};
431

    
432
static const int cc_op_arithb[8] = {
433
    CC_OP_ADDB,
434
    CC_OP_LOGICB,
435
    CC_OP_ADDB,
436
    CC_OP_SUBB,
437
    CC_OP_LOGICB,
438
    CC_OP_SUBB,
439
    CC_OP_LOGICB,
440
    CC_OP_SUBB,
441
};
442

    
443
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
444
    gen_op_cmpxchgb_T0_T1_EAX_cc,
445
    gen_op_cmpxchgw_T0_T1_EAX_cc,
446
    gen_op_cmpxchgl_T0_T1_EAX_cc,
447
};
448

    
449
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
450
    [OT_BYTE] = {
451
        gen_op_rolb_T0_T1_cc,
452
        gen_op_rorb_T0_T1_cc,
453
        gen_op_rclb_T0_T1_cc,
454
        gen_op_rcrb_T0_T1_cc,
455
        gen_op_shlb_T0_T1_cc,
456
        gen_op_shrb_T0_T1_cc,
457
        gen_op_shlb_T0_T1_cc,
458
        gen_op_sarb_T0_T1_cc,
459
    },
460
    [OT_WORD] = {
461
        gen_op_rolw_T0_T1_cc,
462
        gen_op_rorw_T0_T1_cc,
463
        gen_op_rclw_T0_T1_cc,
464
        gen_op_rcrw_T0_T1_cc,
465
        gen_op_shlw_T0_T1_cc,
466
        gen_op_shrw_T0_T1_cc,
467
        gen_op_shlw_T0_T1_cc,
468
        gen_op_sarw_T0_T1_cc,
469
    },
470
    [OT_LONG] = {
471
        gen_op_roll_T0_T1_cc,
472
        gen_op_rorl_T0_T1_cc,
473
        gen_op_rcll_T0_T1_cc,
474
        gen_op_rcrl_T0_T1_cc,
475
        gen_op_shll_T0_T1_cc,
476
        gen_op_shrl_T0_T1_cc,
477
        gen_op_shll_T0_T1_cc,
478
        gen_op_sarl_T0_T1_cc,
479
    },
480
};
481

    
482
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
483
    [0] = {
484
        gen_op_shldw_T0_T1_im_cc,
485
        gen_op_shrdw_T0_T1_im_cc,
486
    },
487
    [1] = {
488
        gen_op_shldl_T0_T1_im_cc,
489
        gen_op_shrdl_T0_T1_im_cc,
490
    },
491
};
492

    
493
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
494
    [0] = {
495
        gen_op_shldw_T0_T1_ECX_cc,
496
        gen_op_shrdw_T0_T1_ECX_cc,
497
    },
498
    [1] = {
499
        gen_op_shldl_T0_T1_ECX_cc,
500
        gen_op_shrdl_T0_T1_ECX_cc,
501
    },
502
};
503

    
504
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
505
    [0] = {
506
        gen_op_btw_T0_T1_cc,
507
        gen_op_btsw_T0_T1_cc,
508
        gen_op_btrw_T0_T1_cc,
509
        gen_op_btcw_T0_T1_cc,
510
    },
511
    [1] = {
512
        gen_op_btl_T0_T1_cc,
513
        gen_op_btsl_T0_T1_cc,
514
        gen_op_btrl_T0_T1_cc,
515
        gen_op_btcl_T0_T1_cc,
516
    },
517
};
518

    
519
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
520
    [0] = {
521
        gen_op_bsfw_T0_cc,
522
        gen_op_bsrw_T0_cc,
523
    },
524
    [1] = {
525
        gen_op_bsfl_T0_cc,
526
        gen_op_bsrl_T0_cc,
527
    },
528
};
529

    
530
static GenOpFunc *gen_op_lds_T0_A0[3] = {
531
    gen_op_ldsb_T0_A0,
532
    gen_op_ldsw_T0_A0,
533
};
534

    
535
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
536
    gen_op_ldub_T0_A0,
537
    gen_op_lduw_T0_A0,
538
};
539

    
540
/* sign does not matter */
541
static GenOpFunc *gen_op_ld_T0_A0[3] = {
542
    gen_op_ldub_T0_A0,
543
    gen_op_lduw_T0_A0,
544
    gen_op_ldl_T0_A0,
545
};
546

    
547
static GenOpFunc *gen_op_ld_T1_A0[3] = {
548
    gen_op_ldub_T1_A0,
549
    gen_op_lduw_T1_A0,
550
    gen_op_ldl_T1_A0,
551
};
552

    
553
static GenOpFunc *gen_op_st_T0_A0[3] = {
554
    gen_op_stb_T0_A0,
555
    gen_op_stw_T0_A0,
556
    gen_op_stl_T0_A0,
557
};
558

    
559
static GenOpFunc *gen_op_movs[6] = {
560
    gen_op_movsb,
561
    gen_op_movsw,
562
    gen_op_movsl,
563
    gen_op_rep_movsb,
564
    gen_op_rep_movsw,
565
    gen_op_rep_movsl,
566
};
567

    
568
static GenOpFunc *gen_op_stos[6] = {
569
    gen_op_stosb,
570
    gen_op_stosw,
571
    gen_op_stosl,
572
    gen_op_rep_stosb,
573
    gen_op_rep_stosw,
574
    gen_op_rep_stosl,
575
};
576

    
577
static GenOpFunc *gen_op_lods[6] = {
578
    gen_op_lodsb,
579
    gen_op_lodsw,
580
    gen_op_lodsl,
581
    gen_op_rep_lodsb,
582
    gen_op_rep_lodsw,
583
    gen_op_rep_lodsl,
584
};
585

    
586
static GenOpFunc *gen_op_scas[9] = {
587
    gen_op_scasb,
588
    gen_op_scasw,
589
    gen_op_scasl,
590
    gen_op_repz_scasb,
591
    gen_op_repz_scasw,
592
    gen_op_repz_scasl,
593
    gen_op_repnz_scasb,
594
    gen_op_repnz_scasw,
595
    gen_op_repnz_scasl,
596
};
597

    
598
static GenOpFunc *gen_op_cmps[9] = {
599
    gen_op_cmpsb,
600
    gen_op_cmpsw,
601
    gen_op_cmpsl,
602
    gen_op_repz_cmpsb,
603
    gen_op_repz_cmpsw,
604
    gen_op_repz_cmpsl,
605
    gen_op_repnz_cmpsb,
606
    gen_op_repnz_cmpsw,
607
    gen_op_repnz_cmpsl,
608
};
609

    
610
static GenOpFunc *gen_op_ins[6] = {
611
    gen_op_insb,
612
    gen_op_insw,
613
    gen_op_insl,
614
    gen_op_rep_insb,
615
    gen_op_rep_insw,
616
    gen_op_rep_insl,
617
};
618

    
619

    
620
static GenOpFunc *gen_op_outs[6] = {
621
    gen_op_outsb,
622
    gen_op_outsw,
623
    gen_op_outsl,
624
    gen_op_rep_outsb,
625
    gen_op_rep_outsw,
626
    gen_op_rep_outsl,
627
};
628

    
629
static GenOpFunc *gen_op_in[3] = {
630
    gen_op_inb_T0_T1,
631
    gen_op_inw_T0_T1,
632
    gen_op_inl_T0_T1,
633
};
634

    
635
static GenOpFunc *gen_op_out[3] = {
636
    gen_op_outb_T0_T1,
637
    gen_op_outw_T0_T1,
638
    gen_op_outl_T0_T1,
639
};
640

    
641
enum {
642
    JCC_O,
643
    JCC_B,
644
    JCC_Z,
645
    JCC_BE,
646
    JCC_S,
647
    JCC_P,
648
    JCC_L,
649
    JCC_LE,
650
};
651

    
652
static GenOpFunc2 *gen_jcc_slow[8] = {
653
    gen_op_jo_cc,
654
    gen_op_jb_cc,
655
    gen_op_jz_cc,
656
    gen_op_jbe_cc,
657
    gen_op_js_cc,
658
    gen_op_jp_cc,
659
    gen_op_jl_cc,
660
    gen_op_jle_cc,
661
};
662
    
663
static GenOpFunc2 *gen_jcc_sub[3][8] = {
664
    [OT_BYTE] = {
665
        NULL,
666
        gen_op_jb_subb,
667
        gen_op_jz_subb,
668
        gen_op_jbe_subb,
669
        gen_op_js_subb,
670
        NULL,
671
        gen_op_jl_subb,
672
        gen_op_jle_subb,
673
    },
674
    [OT_WORD] = {
675
        NULL,
676
        gen_op_jb_subw,
677
        gen_op_jz_subw,
678
        gen_op_jbe_subw,
679
        gen_op_js_subw,
680
        NULL,
681
        gen_op_jl_subw,
682
        gen_op_jle_subw,
683
    },
684
    [OT_LONG] = {
685
        NULL,
686
        gen_op_jb_subl,
687
        gen_op_jz_subl,
688
        gen_op_jbe_subl,
689
        gen_op_js_subl,
690
        NULL,
691
        gen_op_jl_subl,
692
        gen_op_jle_subl,
693
    },
694
};
695
static GenOpFunc2 *gen_op_loop[2][4] = {
696
    [0] = {
697
        gen_op_loopnzw,
698
        gen_op_loopzw,
699
        gen_op_loopw,
700
        gen_op_jecxzw,
701
    },
702
    [1] = {
703
        gen_op_loopnzl,
704
        gen_op_loopzl,
705
        gen_op_loopl,
706
        gen_op_jecxzl,
707
    },
708
};
709

    
710
static GenOpFunc *gen_setcc_slow[8] = {
711
    gen_op_seto_T0_cc,
712
    gen_op_setb_T0_cc,
713
    gen_op_setz_T0_cc,
714
    gen_op_setbe_T0_cc,
715
    gen_op_sets_T0_cc,
716
    gen_op_setp_T0_cc,
717
    gen_op_setl_T0_cc,
718
    gen_op_setle_T0_cc,
719
};
720

    
721
static GenOpFunc *gen_setcc_sub[3][8] = {
722
    [OT_BYTE] = {
723
        NULL,
724
        gen_op_setb_T0_subb,
725
        gen_op_setz_T0_subb,
726
        gen_op_setbe_T0_subb,
727
        gen_op_sets_T0_subb,
728
        NULL,
729
        gen_op_setl_T0_subb,
730
        gen_op_setle_T0_subb,
731
    },
732
    [OT_WORD] = {
733
        NULL,
734
        gen_op_setb_T0_subw,
735
        gen_op_setz_T0_subw,
736
        gen_op_setbe_T0_subw,
737
        gen_op_sets_T0_subw,
738
        NULL,
739
        gen_op_setl_T0_subw,
740
        gen_op_setle_T0_subw,
741
    },
742
    [OT_LONG] = {
743
        NULL,
744
        gen_op_setb_T0_subl,
745
        gen_op_setz_T0_subl,
746
        gen_op_setbe_T0_subl,
747
        gen_op_sets_T0_subl,
748
        NULL,
749
        gen_op_setl_T0_subl,
750
        gen_op_setle_T0_subl,
751
    },
752
};
753

    
754
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
755
    gen_op_fadd_ST0_FT0,
756
    gen_op_fmul_ST0_FT0,
757
    gen_op_fcom_ST0_FT0,
758
    gen_op_fcom_ST0_FT0,
759
    gen_op_fsub_ST0_FT0,
760
    gen_op_fsubr_ST0_FT0,
761
    gen_op_fdiv_ST0_FT0,
762
    gen_op_fdivr_ST0_FT0,
763
};
764

    
765
/* NOTE the exception in "r" op ordering */
766
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
767
    gen_op_fadd_STN_ST0,
768
    gen_op_fmul_STN_ST0,
769
    NULL,
770
    NULL,
771
    gen_op_fsubr_STN_ST0,
772
    gen_op_fsub_STN_ST0,
773
    gen_op_fdivr_STN_ST0,
774
    gen_op_fdiv_STN_ST0,
775
};
776

    
777
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
778
{
779
    if (d != OR_TMP0)
780
        gen_op_mov_TN_reg[ot][0][d]();
781
    if (s != OR_TMP1)
782
        gen_op_mov_TN_reg[ot][1][s]();
783
    if (op == OP_ADCL || op == OP_SBBL) {
784
        if (s1->cc_op != CC_OP_DYNAMIC)
785
            gen_op_set_cc_op(s1->cc_op);
786
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
787
        s1->cc_op = CC_OP_DYNAMIC;
788
    } else {
789
        gen_op_arith_T0_T1_cc[op]();
790
        s1->cc_op = cc_op_arithb[op] + ot;
791
    }
792
    if (d != OR_TMP0 && op != OP_CMPL)
793
        gen_op_mov_reg_T0[ot][d]();
794
}
795

    
796
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
797
{
798
    gen_op_movl_T1_im(c);
799
    gen_op(s1, op, ot, d, OR_TMP1);
800
}
801

    
802
static void gen_inc(DisasContext *s1, int ot, int d, int c)
803
{
804
    if (d != OR_TMP0)
805
        gen_op_mov_TN_reg[ot][0][d]();
806
    if (s1->cc_op != CC_OP_DYNAMIC)
807
        gen_op_set_cc_op(s1->cc_op);
808
    if (c > 0) {
809
        gen_op_incl_T0_cc();
810
        s1->cc_op = CC_OP_INCB + ot;
811
    } else {
812
        gen_op_decl_T0_cc();
813
        s1->cc_op = CC_OP_DECB + ot;
814
    }
815
    if (d != OR_TMP0)
816
        gen_op_mov_reg_T0[ot][d]();
817
}
818

    
819
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
820
{
821
    if (d != OR_TMP0)
822
        gen_op_mov_TN_reg[ot][0][d]();
823
    if (s != OR_TMP1)
824
        gen_op_mov_TN_reg[ot][1][s]();
825
    /* for zero counts, flags are not updated, so must do it dynamically */
826
    if (s1->cc_op != CC_OP_DYNAMIC)
827
        gen_op_set_cc_op(s1->cc_op);
828

    
829
    gen_op_shift_T0_T1_cc[ot][op]();
830

    
831
    if (d != OR_TMP0)
832
        gen_op_mov_reg_T0[ot][d]();
833
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
834
}
835

    
836
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
837
{
838
    /* currently not optimized */
839
    gen_op_movl_T1_im(c);
840
    gen_shift(s1, op, ot, d, OR_TMP1);
841
}
842

    
843
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
844
{
845
    int havesib;
846
    int base, disp;
847
    int index;
848
    int scale;
849
    int opreg;
850
    int mod, rm, code, override, must_add_seg;
851

    
852
    /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
853
    override = -1;
854
    must_add_seg = s->addseg;
855
    if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | 
856
                     PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
857
        if (s->prefix & PREFIX_ES)
858
            override = R_ES;
859
        else if (s->prefix & PREFIX_CS)
860
            override = R_CS;
861
        else if (s->prefix & PREFIX_SS)
862
            override = R_SS;
863
        else if (s->prefix & PREFIX_DS)
864
            override = R_DS;
865
        else if (s->prefix & PREFIX_FS)
866
            override = R_FS;
867
        else
868
            override = R_GS;
869
        must_add_seg = 1;
870
    }
871

    
872
    mod = (modrm >> 6) & 3;
873
    rm = modrm & 7;
874

    
875
    if (s->aflag) {
876

    
877
        havesib = 0;
878
        base = rm;
879
        index = 0;
880
        scale = 0;
881
        
882
        if (base == 4) {
883
            havesib = 1;
884
            code = ldub(s->pc++);
885
            scale = (code >> 6) & 3;
886
            index = (code >> 3) & 7;
887
            base = code & 7;
888
        }
889

    
890
        switch (mod) {
891
        case 0:
892
            if (base == 5) {
893
                base = -1;
894
                disp = ldl(s->pc);
895
                s->pc += 4;
896
            } else {
897
                disp = 0;
898
            }
899
            break;
900
        case 1:
901
            disp = (int8_t)ldub(s->pc++);
902
            break;
903
        default:
904
        case 2:
905
            disp = ldl(s->pc);
906
            s->pc += 4;
907
            break;
908
        }
909
        
910
        if (base >= 0) {
911
            gen_op_movl_A0_reg[base]();
912
            if (disp != 0)
913
                gen_op_addl_A0_im(disp);
914
        } else {
915
            gen_op_movl_A0_im(disp);
916
        }
917
        if (havesib && (index != 4 || scale != 0)) {
918
            gen_op_addl_A0_reg_sN[scale][index]();
919
        }
920
        if (must_add_seg) {
921
            if (override < 0) {
922
                if (base == R_EBP || base == R_ESP)
923
                    override = R_SS;
924
                else
925
                    override = R_DS;
926
            }
927
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
928
        }
929
    } else {
930
        switch (mod) {
931
        case 0:
932
            if (rm == 6) {
933
                disp = lduw(s->pc);
934
                s->pc += 2;
935
                gen_op_movl_A0_im(disp);
936
                rm = 0; /* avoid SS override */
937
                goto no_rm;
938
            } else {
939
                disp = 0;
940
            }
941
            break;
942
        case 1:
943
            disp = (int8_t)ldub(s->pc++);
944
            break;
945
        default:
946
        case 2:
947
            disp = lduw(s->pc);
948
            s->pc += 2;
949
            break;
950
        }
951
        switch(rm) {
952
        case 0:
953
            gen_op_movl_A0_reg[R_EBX]();
954
            gen_op_addl_A0_reg_sN[0][R_ESI]();
955
            break;
956
        case 1:
957
            gen_op_movl_A0_reg[R_EBX]();
958
            gen_op_addl_A0_reg_sN[0][R_EDI]();
959
            break;
960
        case 2:
961
            gen_op_movl_A0_reg[R_EBP]();
962
            gen_op_addl_A0_reg_sN[0][R_ESI]();
963
            break;
964
        case 3:
965
            gen_op_movl_A0_reg[R_EBP]();
966
            gen_op_addl_A0_reg_sN[0][R_EDI]();
967
            break;
968
        case 4:
969
            gen_op_movl_A0_reg[R_ESI]();
970
            break;
971
        case 5:
972
            gen_op_movl_A0_reg[R_EDI]();
973
            break;
974
        case 6:
975
            gen_op_movl_A0_reg[R_EBP]();
976
            break;
977
        default:
978
        case 7:
979
            gen_op_movl_A0_reg[R_EBX]();
980
            break;
981
        }
982
        if (disp != 0)
983
            gen_op_addl_A0_im(disp);
984
        gen_op_andl_A0_ffff();
985
    no_rm:
986
        if (must_add_seg) {
987
            if (override < 0) {
988
                if (rm == 2 || rm == 3 || rm == 6)
989
                    override = R_SS;
990
                else
991
                    override = R_DS;
992
            }
993
            gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
994
        }
995
    }
996

    
997
    opreg = OR_A0;
998
    disp = 0;
999
    *reg_ptr = opreg;
1000
    *offset_ptr = disp;
1001
}
1002

    
1003
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1004
   OR_TMP0 */
1005
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1006
{
1007
    int mod, rm, opreg, disp;
1008

    
1009
    mod = (modrm >> 6) & 3;
1010
    rm = modrm & 7;
1011
    if (mod == 3) {
1012
        if (is_store) {
1013
            if (reg != OR_TMP0)
1014
                gen_op_mov_TN_reg[ot][0][reg]();
1015
            gen_op_mov_reg_T0[ot][rm]();
1016
        } else {
1017
            gen_op_mov_TN_reg[ot][0][rm]();
1018
            if (reg != OR_TMP0)
1019
                gen_op_mov_reg_T0[ot][reg]();
1020
        }
1021
    } else {
1022
        gen_lea_modrm(s, modrm, &opreg, &disp);
1023
        if (is_store) {
1024
            if (reg != OR_TMP0)
1025
                gen_op_mov_TN_reg[ot][0][reg]();
1026
            gen_op_st_T0_A0[ot]();
1027
        } else {
1028
            gen_op_ld_T0_A0[ot]();
1029
            if (reg != OR_TMP0)
1030
                gen_op_mov_reg_T0[ot][reg]();
1031
        }
1032
    }
1033
}
1034

    
1035
static inline uint32_t insn_get(DisasContext *s, int ot)
1036
{
1037
    uint32_t ret;
1038

    
1039
    switch(ot) {
1040
    case OT_BYTE:
1041
        ret = ldub(s->pc);
1042
        s->pc++;
1043
        break;
1044
    case OT_WORD:
1045
        ret = lduw(s->pc);
1046
        s->pc += 2;
1047
        break;
1048
    default:
1049
    case OT_LONG:
1050
        ret = ldl(s->pc);
1051
        s->pc += 4;
1052
        break;
1053
    }
1054
    return ret;
1055
}
1056

    
1057
static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1058
{
1059
    int inv, jcc_op;
1060
    GenOpFunc2 *func;
1061

    
1062
    inv = b & 1;
1063
    jcc_op = (b >> 1) & 7;
1064
    switch(s->cc_op) {
1065
        /* we optimize the cmp/jcc case */
1066
    case CC_OP_SUBB:
1067
    case CC_OP_SUBW:
1068
    case CC_OP_SUBL:
1069
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1070
        if (!func)
1071
            goto slow_jcc;
1072
        break;
1073
        
1074
        /* some jumps are easy to compute */
1075
    case CC_OP_ADDB:
1076
    case CC_OP_ADDW:
1077
    case CC_OP_ADDL:
1078
    case CC_OP_ADCB:
1079
    case CC_OP_ADCW:
1080
    case CC_OP_ADCL:
1081
    case CC_OP_SBBB:
1082
    case CC_OP_SBBW:
1083
    case CC_OP_SBBL:
1084
    case CC_OP_LOGICB:
1085
    case CC_OP_LOGICW:
1086
    case CC_OP_LOGICL:
1087
    case CC_OP_INCB:
1088
    case CC_OP_INCW:
1089
    case CC_OP_INCL:
1090
    case CC_OP_DECB:
1091
    case CC_OP_DECW:
1092
    case CC_OP_DECL:
1093
    case CC_OP_SHLB:
1094
    case CC_OP_SHLW:
1095
    case CC_OP_SHLL:
1096
    case CC_OP_SARB:
1097
    case CC_OP_SARW:
1098
    case CC_OP_SARL:
1099
        switch(jcc_op) {
1100
        case JCC_Z:
1101
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1102
            break;
1103
        case JCC_S:
1104
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1105
            break;
1106
        default:
1107
            goto slow_jcc;
1108
        }
1109
        break;
1110
    default:
1111
    slow_jcc:
1112
        if (s->cc_op != CC_OP_DYNAMIC)
1113
            gen_op_set_cc_op(s->cc_op);
1114
        func = gen_jcc_slow[jcc_op];
1115
        break;
1116
    }
1117
    if (!inv) {
1118
        func(val, next_eip);
1119
    } else {
1120
        func(next_eip, val);
1121
    }
1122
}
1123

    
1124
static void gen_setcc(DisasContext *s, int b)
1125
{
1126
    int inv, jcc_op;
1127
    GenOpFunc *func;
1128

    
1129
    inv = b & 1;
1130
    jcc_op = (b >> 1) & 7;
1131
    switch(s->cc_op) {
1132
        /* we optimize the cmp/jcc case */
1133
    case CC_OP_SUBB:
1134
    case CC_OP_SUBW:
1135
    case CC_OP_SUBL:
1136
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1137
        if (!func)
1138
            goto slow_jcc;
1139
        break;
1140
        
1141
        /* some jumps are easy to compute */
1142
    case CC_OP_ADDB:
1143
    case CC_OP_ADDW:
1144
    case CC_OP_ADDL:
1145
    case CC_OP_LOGICB:
1146
    case CC_OP_LOGICW:
1147
    case CC_OP_LOGICL:
1148
    case CC_OP_INCB:
1149
    case CC_OP_INCW:
1150
    case CC_OP_INCL:
1151
    case CC_OP_DECB:
1152
    case CC_OP_DECW:
1153
    case CC_OP_DECL:
1154
    case CC_OP_SHLB:
1155
    case CC_OP_SHLW:
1156
    case CC_OP_SHLL:
1157
        switch(jcc_op) {
1158
        case JCC_Z:
1159
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1160
            break;
1161
        case JCC_S:
1162
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1163
            break;
1164
        default:
1165
            goto slow_jcc;
1166
        }
1167
        break;
1168
    default:
1169
    slow_jcc:
1170
        if (s->cc_op != CC_OP_DYNAMIC)
1171
            gen_op_set_cc_op(s->cc_op);
1172
        func = gen_setcc_slow[jcc_op];
1173
        break;
1174
    }
1175
    func();
1176
    if (inv) {
1177
        gen_op_xor_T0_1();
1178
    }
1179
}
1180

    
1181
/* move T0 to seg_reg and compute if the CPU state may change */
1182
static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1183
{
1184
    gen_op_movl_seg_T0(seg_reg);
1185
    if (!s->addseg && seg_reg < R_FS)
1186
        s->is_jmp = 2; /* abort translation because the register may
1187
                          have a non zero base */
1188
}
1189

    
1190
/* generate a push. It depends on ss32, addseg and dflag */
1191
static void gen_push_T0(DisasContext *s)
1192
{
1193
    if (s->ss32) {
1194
        if (!s->addseg) {
1195
            if (s->dflag)
1196
                gen_op_pushl_T0();
1197
            else
1198
                gen_op_pushw_T0();
1199
        } else {
1200
            if (s->dflag)
1201
                gen_op_pushl_ss32_T0();
1202
            else
1203
                gen_op_pushw_ss32_T0();
1204
        }
1205
    } else {
1206
        if (s->dflag)
1207
            gen_op_pushl_ss16_T0();
1208
        else
1209
            gen_op_pushw_ss16_T0();
1210
    }
1211
}
1212

    
1213
/* two step pop is necessary for precise exceptions */
1214
static void gen_pop_T0(DisasContext *s)
1215
{
1216
    if (s->ss32) {
1217
        if (!s->addseg) {
1218
            if (s->dflag)
1219
                gen_op_popl_T0();
1220
            else
1221
                gen_op_popw_T0();
1222
        } else {
1223
            if (s->dflag)
1224
                gen_op_popl_ss32_T0();
1225
            else
1226
                gen_op_popw_ss32_T0();
1227
        }
1228
    } else {
1229
        if (s->dflag)
1230
            gen_op_popl_ss16_T0();
1231
        else
1232
            gen_op_popw_ss16_T0();
1233
    }
1234
}
1235

    
1236
static void gen_pop_update(DisasContext *s)
1237
{
1238
    if (s->ss32) {
1239
        if (s->dflag)
1240
            gen_op_addl_ESP_4();
1241
        else
1242
            gen_op_addl_ESP_2();
1243
    } else {
1244
        if (s->dflag)
1245
            gen_op_addw_ESP_4();
1246
        else
1247
            gen_op_addw_ESP_2();
1248
    }
1249
}
1250

    
1251
/* NOTE: wrap around in 16 bit not fully handled */
1252
static void gen_pusha(DisasContext *s)
1253
{
1254
    int i;
1255
    gen_op_movl_A0_ESP();
1256
    gen_op_addl_A0_im(-16 <<  s->dflag);
1257
    if (!s->ss32)
1258
        gen_op_andl_A0_ffff();
1259
    gen_op_movl_T1_A0();
1260
    if (s->addseg)
1261
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1262
    for(i = 0;i < 8; i++) {
1263
        gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1264
        gen_op_st_T0_A0[OT_WORD + s->dflag]();
1265
        gen_op_addl_A0_im(2 <<  s->dflag);
1266
    }
1267
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1268
}
1269

    
1270
/* NOTE: wrap around in 16 bit not fully handled */
1271
static void gen_popa(DisasContext *s)
1272
{
1273
    int i;
1274
    gen_op_movl_A0_ESP();
1275
    if (!s->ss32)
1276
        gen_op_andl_A0_ffff();
1277
    gen_op_movl_T1_A0();
1278
    gen_op_addl_T1_im(16 <<  s->dflag);
1279
    if (s->addseg)
1280
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1281
    for(i = 0;i < 8; i++) {
1282
        /* ESP is not reloaded */
1283
        if (i != 3) {
1284
            gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1285
            gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1286
        }
1287
        gen_op_addl_A0_im(2 <<  s->dflag);
1288
    }
1289
    gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1290
}
1291

    
1292
/* NOTE: wrap around in 16 bit not fully handled */
1293
/* XXX: check this */
1294
static void gen_enter(DisasContext *s, int esp_addend, int level)
1295
{
1296
    int ot, level1, addend, opsize;
1297

    
1298
    ot = s->dflag + OT_WORD;
1299
    level &= 0x1f;
1300
    level1 = level;
1301
    opsize = 2 << s->dflag;
1302

    
1303
    gen_op_movl_A0_ESP();
1304
    gen_op_addl_A0_im(-opsize);
1305
    if (!s->ss32)
1306
        gen_op_andl_A0_ffff();
1307
    gen_op_movl_T1_A0();
1308
    if (s->addseg)
1309
        gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1310
    /* push bp */
1311
    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1312
    gen_op_st_T0_A0[ot]();
1313
    if (level) {
1314
        while (level--) {
1315
            gen_op_addl_A0_im(-opsize);
1316
            gen_op_addl_T0_im(-opsize);
1317
            gen_op_st_T0_A0[ot]();
1318
        }
1319
        gen_op_addl_A0_im(-opsize);
1320
        /* XXX: add st_T1_A0 ? */
1321
        gen_op_movl_T0_T1();
1322
        gen_op_st_T0_A0[ot]();
1323
    }
1324
    gen_op_mov_reg_T1[ot][R_EBP]();
1325
    addend = -esp_addend;
1326
    if (level1)
1327
        addend -= opsize * (level1 + 1);
1328
    gen_op_addl_T1_im(addend);
1329
    gen_op_mov_reg_T1[ot][R_ESP]();
1330
}
1331

    
1332
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1333
   is set to true if the instruction sets the PC (last instruction of
1334
   a basic block) */
1335
long disas_insn(DisasContext *s, uint8_t *pc_start)
1336
{
1337
    int b, prefixes, aflag, dflag;
1338
    int shift, ot;
1339
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1340
    unsigned int next_eip;
1341

    
1342
    s->pc = pc_start;
1343
    prefixes = 0;
1344
    aflag = s->code32;
1345
    dflag = s->code32;
1346
    //    cur_pc = s->pc; /* for insn generation */
1347
 next_byte:
1348
    b = ldub(s->pc);
1349
    s->pc++;
1350
    /* check prefixes */
1351
    switch (b) {
1352
    case 0xf3:
1353
        prefixes |= PREFIX_REPZ;
1354
        goto next_byte;
1355
    case 0xf2:
1356
        prefixes |= PREFIX_REPNZ;
1357
        goto next_byte;
1358
    case 0xf0:
1359
        prefixes |= PREFIX_LOCK;
1360
        goto next_byte;
1361
    case 0x2e:
1362
        prefixes |= PREFIX_CS;
1363
        goto next_byte;
1364
    case 0x36:
1365
        prefixes |= PREFIX_SS;
1366
        goto next_byte;
1367
    case 0x3e:
1368
        prefixes |= PREFIX_DS;
1369
        goto next_byte;
1370
    case 0x26:
1371
        prefixes |= PREFIX_ES;
1372
        goto next_byte;
1373
    case 0x64:
1374
        prefixes |= PREFIX_FS;
1375
        goto next_byte;
1376
    case 0x65:
1377
        prefixes |= PREFIX_GS;
1378
        goto next_byte;
1379
    case 0x66:
1380
        prefixes |= PREFIX_DATA;
1381
        goto next_byte;
1382
    case 0x67:
1383
        prefixes |= PREFIX_ADR;
1384
        goto next_byte;
1385
    case 0x9b:
1386
        prefixes |= PREFIX_FWAIT;
1387
        goto next_byte;
1388
    }
1389

    
1390
    if (prefixes & PREFIX_DATA)
1391
        dflag ^= 1;
1392
    if (prefixes & PREFIX_ADR)
1393
        aflag ^= 1;
1394

    
1395
    s->prefix = prefixes;
1396
    s->aflag = aflag;
1397
    s->dflag = dflag;
1398

    
1399
    /* lock generation */
1400
    if (prefixes & PREFIX_LOCK)
1401
        gen_op_lock();
1402

    
1403
    /* now check op code */
1404
 reswitch:
1405
    switch(b) {
1406
    case 0x0f:
1407
        /**************************/
1408
        /* extended op code */
1409
        b = ldub(s->pc++) | 0x100;
1410
        goto reswitch;
1411
        
1412
        /**************************/
1413
        /* arith & logic */
1414
    case 0x00 ... 0x05:
1415
    case 0x08 ... 0x0d:
1416
    case 0x10 ... 0x15:
1417
    case 0x18 ... 0x1d:
1418
    case 0x20 ... 0x25:
1419
    case 0x28 ... 0x2d:
1420
    case 0x30 ... 0x35:
1421
    case 0x38 ... 0x3d:
1422
        {
1423
            int op, f, val;
1424
            op = (b >> 3) & 7;
1425
            f = (b >> 1) & 3;
1426

    
1427
            if ((b & 1) == 0)
1428
                ot = OT_BYTE;
1429
            else
1430
                ot = dflag ? OT_LONG : OT_WORD;
1431
            
1432
            switch(f) {
1433
            case 0: /* OP Ev, Gv */
1434
                modrm = ldub(s->pc++);
1435
                reg = ((modrm >> 3) & 7) + OR_EAX;
1436
                mod = (modrm >> 6) & 3;
1437
                rm = modrm & 7;
1438
                if (mod != 3) {
1439
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1440
                    gen_op_ld_T0_A0[ot]();
1441
                    opreg = OR_TMP0;
1442
                } else {
1443
                    opreg = OR_EAX + rm;
1444
                }
1445
                gen_op(s, op, ot, opreg, reg);
1446
                if (mod != 3 && op != 7) {
1447
                    gen_op_st_T0_A0[ot]();
1448
                }
1449
                break;
1450
            case 1: /* OP Gv, Ev */
1451
                modrm = ldub(s->pc++);
1452
                mod = (modrm >> 6) & 3;
1453
                reg = ((modrm >> 3) & 7) + OR_EAX;
1454
                rm = modrm & 7;
1455
                if (mod != 3) {
1456
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1457
                    gen_op_ld_T1_A0[ot]();
1458
                    opreg = OR_TMP1;
1459
                } else {
1460
                    opreg = OR_EAX + rm;
1461
                }
1462
                gen_op(s, op, ot, reg, opreg);
1463
                break;
1464
            case 2: /* OP A, Iv */
1465
                val = insn_get(s, ot);
1466
                gen_opi(s, op, ot, OR_EAX, val);
1467
                break;
1468
            }
1469
        }
1470
        break;
1471

    
1472
    case 0x80: /* GRP1 */
1473
    case 0x81:
1474
    case 0x83:
1475
        {
1476
            int val;
1477

    
1478
            if ((b & 1) == 0)
1479
                ot = OT_BYTE;
1480
            else
1481
                ot = dflag ? OT_LONG : OT_WORD;
1482
            
1483
            modrm = ldub(s->pc++);
1484
            mod = (modrm >> 6) & 3;
1485
            rm = modrm & 7;
1486
            op = (modrm >> 3) & 7;
1487
            
1488
            if (mod != 3) {
1489
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1490
                gen_op_ld_T0_A0[ot]();
1491
                opreg = OR_TMP0;
1492
            } else {
1493
                opreg = rm + OR_EAX;
1494
            }
1495

    
1496
            switch(b) {
1497
            default:
1498
            case 0x80:
1499
            case 0x81:
1500
                val = insn_get(s, ot);
1501
                break;
1502
            case 0x83:
1503
                val = (int8_t)insn_get(s, OT_BYTE);
1504
                break;
1505
            }
1506

    
1507
            gen_opi(s, op, ot, opreg, val);
1508
            if (op != 7 && mod != 3) {
1509
                gen_op_st_T0_A0[ot]();
1510
            }
1511
        }
1512
        break;
1513

    
1514
        /**************************/
1515
        /* inc, dec, and other misc arith */
1516
    case 0x40 ... 0x47: /* inc Gv */
1517
        ot = dflag ? OT_LONG : OT_WORD;
1518
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1519
        break;
1520
    case 0x48 ... 0x4f: /* dec Gv */
1521
        ot = dflag ? OT_LONG : OT_WORD;
1522
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1523
        break;
1524
    case 0xf6: /* GRP3 */
1525
    case 0xf7:
1526
        if ((b & 1) == 0)
1527
            ot = OT_BYTE;
1528
        else
1529
            ot = dflag ? OT_LONG : OT_WORD;
1530

    
1531
        modrm = ldub(s->pc++);
1532
        mod = (modrm >> 6) & 3;
1533
        rm = modrm & 7;
1534
        op = (modrm >> 3) & 7;
1535
        if (mod != 3) {
1536
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1537
            gen_op_ld_T0_A0[ot]();
1538
        } else {
1539
            gen_op_mov_TN_reg[ot][0][rm]();
1540
        }
1541

    
1542
        switch(op) {
1543
        case 0: /* test */
1544
            val = insn_get(s, ot);
1545
            gen_op_movl_T1_im(val);
1546
            gen_op_testl_T0_T1_cc();
1547
            s->cc_op = CC_OP_LOGICB + ot;
1548
            break;
1549
        case 2: /* not */
1550
            gen_op_notl_T0();
1551
            if (mod != 3) {
1552
                gen_op_st_T0_A0[ot]();
1553
            } else {
1554
                gen_op_mov_reg_T0[ot][rm]();
1555
            }
1556
            break;
1557
        case 3: /* neg */
1558
            gen_op_negl_T0_cc();
1559
            if (mod != 3) {
1560
                gen_op_st_T0_A0[ot]();
1561
            } else {
1562
                gen_op_mov_reg_T0[ot][rm]();
1563
            }
1564
            s->cc_op = CC_OP_SUBB + ot;
1565
            break;
1566
        case 4: /* mul */
1567
            switch(ot) {
1568
            case OT_BYTE:
1569
                gen_op_mulb_AL_T0();
1570
                break;
1571
            case OT_WORD:
1572
                gen_op_mulw_AX_T0();
1573
                break;
1574
            default:
1575
            case OT_LONG:
1576
                gen_op_mull_EAX_T0();
1577
                break;
1578
            }
1579
            s->cc_op = CC_OP_MUL;
1580
            break;
1581
        case 5: /* imul */
1582
            switch(ot) {
1583
            case OT_BYTE:
1584
                gen_op_imulb_AL_T0();
1585
                break;
1586
            case OT_WORD:
1587
                gen_op_imulw_AX_T0();
1588
                break;
1589
            default:
1590
            case OT_LONG:
1591
                gen_op_imull_EAX_T0();
1592
                break;
1593
            }
1594
            s->cc_op = CC_OP_MUL;
1595
            break;
1596
        case 6: /* div */
1597
            switch(ot) {
1598
            case OT_BYTE:
1599
                gen_op_divb_AL_T0();
1600
                break;
1601
            case OT_WORD:
1602
                gen_op_divw_AX_T0();
1603
                break;
1604
            default:
1605
            case OT_LONG:
1606
                gen_op_divl_EAX_T0();
1607
                break;
1608
            }
1609
            break;
1610
        case 7: /* idiv */
1611
            switch(ot) {
1612
            case OT_BYTE:
1613
                gen_op_idivb_AL_T0();
1614
                break;
1615
            case OT_WORD:
1616
                gen_op_idivw_AX_T0();
1617
                break;
1618
            default:
1619
            case OT_LONG:
1620
                gen_op_idivl_EAX_T0();
1621
                break;
1622
            }
1623
            break;
1624
        default:
1625
            goto illegal_op;
1626
        }
1627
        break;
1628

    
1629
    case 0xfe: /* GRP4 */
1630
    case 0xff: /* GRP5 */
1631
        if ((b & 1) == 0)
1632
            ot = OT_BYTE;
1633
        else
1634
            ot = dflag ? OT_LONG : OT_WORD;
1635

    
1636
        modrm = ldub(s->pc++);
1637
        mod = (modrm >> 6) & 3;
1638
        rm = modrm & 7;
1639
        op = (modrm >> 3) & 7;
1640
        if (op >= 2 && b == 0xfe) {
1641
            goto illegal_op;
1642
        }
1643
        if (mod != 3) {
1644
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1645
            if (op != 3 && op != 5)
1646
                gen_op_ld_T0_A0[ot]();
1647
        } else {
1648
            gen_op_mov_TN_reg[ot][0][rm]();
1649
        }
1650

    
1651
        switch(op) {
1652
        case 0: /* inc Ev */
1653
            gen_inc(s, ot, OR_TMP0, 1);
1654
            if (mod != 3)
1655
                gen_op_st_T0_A0[ot]();
1656
            else
1657
                gen_op_mov_reg_T0[ot][rm]();
1658
            break;
1659
        case 1: /* dec Ev */
1660
            gen_inc(s, ot, OR_TMP0, -1);
1661
            if (mod != 3)
1662
                gen_op_st_T0_A0[ot]();
1663
            else
1664
                gen_op_mov_reg_T0[ot][rm]();
1665
            break;
1666
        case 2: /* call Ev */
1667
            /* XXX: optimize if memory (no and is necessary) */
1668
            if (s->dflag == 0)
1669
                gen_op_andl_T0_ffff();
1670
            gen_op_jmp_T0();
1671
            next_eip = s->pc - s->cs_base;
1672
            gen_op_movl_T0_im(next_eip);
1673
            gen_push_T0(s);
1674
            s->is_jmp = 1;
1675
            break;
1676
        case 3: /* lcall Ev */
1677
            /* push return segment + offset */
1678
            gen_op_movl_T0_seg(R_CS);
1679
            gen_push_T0(s);
1680
            next_eip = s->pc - s->cs_base;
1681
            gen_op_movl_T0_im(next_eip);
1682
            gen_push_T0(s);
1683

    
1684
            gen_op_ld_T1_A0[ot]();
1685
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1686
            gen_op_lduw_T0_A0();
1687
            gen_movl_seg_T0(s, R_CS);
1688
            gen_op_movl_T0_T1();
1689
            gen_op_jmp_T0();
1690
            s->is_jmp = 1;
1691
            break;
1692
        case 4: /* jmp Ev */
1693
            if (s->dflag == 0)
1694
                gen_op_andl_T0_ffff();
1695
            gen_op_jmp_T0();
1696
            s->is_jmp = 1;
1697
            break;
1698
        case 5: /* ljmp Ev */
1699
            gen_op_ld_T1_A0[ot]();
1700
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1701
            gen_op_lduw_T0_A0();
1702
            gen_movl_seg_T0(s, R_CS);
1703
            gen_op_movl_T0_T1();
1704
            gen_op_jmp_T0();
1705
            s->is_jmp = 1;
1706
            break;
1707
        case 6: /* push Ev */
1708
            gen_push_T0(s);
1709
            break;
1710
        default:
1711
            goto illegal_op;
1712
        }
1713
        break;
1714

    
1715
    case 0x84: /* test Ev, Gv */
1716
    case 0x85: 
1717
        if ((b & 1) == 0)
1718
            ot = OT_BYTE;
1719
        else
1720
            ot = dflag ? OT_LONG : OT_WORD;
1721

    
1722
        modrm = ldub(s->pc++);
1723
        mod = (modrm >> 6) & 3;
1724
        rm = modrm & 7;
1725
        reg = (modrm >> 3) & 7;
1726
        
1727
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1728
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1729
        gen_op_testl_T0_T1_cc();
1730
        s->cc_op = CC_OP_LOGICB + ot;
1731
        break;
1732
        
1733
    case 0xa8: /* test eAX, Iv */
1734
    case 0xa9:
1735
        if ((b & 1) == 0)
1736
            ot = OT_BYTE;
1737
        else
1738
            ot = dflag ? OT_LONG : OT_WORD;
1739
        val = insn_get(s, ot);
1740

    
1741
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1742
        gen_op_movl_T1_im(val);
1743
        gen_op_testl_T0_T1_cc();
1744
        s->cc_op = CC_OP_LOGICB + ot;
1745
        break;
1746
        
1747
    case 0x98: /* CWDE/CBW */
1748
        if (dflag)
1749
            gen_op_movswl_EAX_AX();
1750
        else
1751
            gen_op_movsbw_AX_AL();
1752
        break;
1753
    case 0x99: /* CDQ/CWD */
1754
        if (dflag)
1755
            gen_op_movslq_EDX_EAX();
1756
        else
1757
            gen_op_movswl_DX_AX();
1758
        break;
1759
    case 0x1af: /* imul Gv, Ev */
1760
    case 0x69: /* imul Gv, Ev, I */
1761
    case 0x6b:
1762
        ot = dflag ? OT_LONG : OT_WORD;
1763
        modrm = ldub(s->pc++);
1764
        reg = ((modrm >> 3) & 7) + OR_EAX;
1765
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1766
        if (b == 0x69) {
1767
            val = insn_get(s, ot);
1768
            gen_op_movl_T1_im(val);
1769
        } else if (b == 0x6b) {
1770
            val = insn_get(s, OT_BYTE);
1771
            gen_op_movl_T1_im(val);
1772
        } else {
1773
            gen_op_mov_TN_reg[ot][1][reg]();
1774
        }
1775

    
1776
        if (ot == OT_LONG) {
1777
            gen_op_imull_T0_T1();
1778
        } else {
1779
            gen_op_imulw_T0_T1();
1780
        }
1781
        gen_op_mov_reg_T0[ot][reg]();
1782
        s->cc_op = CC_OP_MUL;
1783
        break;
1784
    case 0x1c0:
1785
    case 0x1c1: /* xadd Ev, Gv */
1786
        if ((b & 1) == 0)
1787
            ot = OT_BYTE;
1788
        else
1789
            ot = dflag ? OT_LONG : OT_WORD;
1790
        modrm = ldub(s->pc++);
1791
        reg = (modrm >> 3) & 7;
1792
        mod = (modrm >> 6) & 3;
1793
        if (mod == 3) {
1794
            rm = modrm & 7;
1795
            gen_op_mov_TN_reg[ot][0][reg]();
1796
            gen_op_mov_TN_reg[ot][1][rm]();
1797
            gen_op_addl_T0_T1_cc();
1798
            gen_op_mov_reg_T0[ot][rm]();
1799
            gen_op_mov_reg_T1[ot][reg]();
1800
        } else {
1801
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1802
            gen_op_mov_TN_reg[ot][0][reg]();
1803
            gen_op_ld_T1_A0[ot]();
1804
            gen_op_addl_T0_T1_cc();
1805
            gen_op_st_T0_A0[ot]();
1806
            gen_op_mov_reg_T1[ot][reg]();
1807
        }
1808
        s->cc_op = CC_OP_ADDB + ot;
1809
        break;
1810
    case 0x1b0:
1811
    case 0x1b1: /* cmpxchg Ev, Gv */
1812
        if ((b & 1) == 0)
1813
            ot = OT_BYTE;
1814
        else
1815
            ot = dflag ? OT_LONG : OT_WORD;
1816
        modrm = ldub(s->pc++);
1817
        reg = (modrm >> 3) & 7;
1818
        mod = (modrm >> 6) & 3;
1819
        gen_op_mov_TN_reg[ot][1][reg]();
1820
        if (mod == 3) {
1821
            rm = modrm & 7;
1822
            gen_op_mov_TN_reg[ot][0][rm]();
1823
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1824
            gen_op_mov_reg_T0[ot][rm]();
1825
        } else {
1826
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1827
            gen_op_ld_T0_A0[ot]();
1828
            gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1829
            gen_op_st_T0_A0[ot]();
1830
        }
1831
        s->cc_op = CC_OP_SUBB + ot;
1832
        break;
1833
        
1834
        /**************************/
1835
        /* push/pop */
1836
    case 0x50 ... 0x57: /* push */
1837
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1838
        gen_push_T0(s);
1839
        break;
1840
    case 0x58 ... 0x5f: /* pop */
1841
        ot = dflag ? OT_LONG : OT_WORD;
1842
        gen_pop_T0(s);
1843
        gen_op_mov_reg_T0[ot][b & 7]();
1844
        gen_pop_update(s);
1845
        break;
1846
    case 0x60: /* pusha */
1847
        gen_pusha(s);
1848
        break;
1849
    case 0x61: /* popa */
1850
        gen_popa(s);
1851
        break;
1852
    case 0x68: /* push Iv */
1853
    case 0x6a:
1854
        ot = dflag ? OT_LONG : OT_WORD;
1855
        if (b == 0x68)
1856
            val = insn_get(s, ot);
1857
        else
1858
            val = (int8_t)insn_get(s, OT_BYTE);
1859
        gen_op_movl_T0_im(val);
1860
        gen_push_T0(s);
1861
        break;
1862
    case 0x8f: /* pop Ev */
1863
        ot = dflag ? OT_LONG : OT_WORD;
1864
        modrm = ldub(s->pc++);
1865
        gen_pop_T0(s);
1866
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1867
        gen_pop_update(s);
1868
        break;
1869
    case 0xc8: /* enter */
1870
        {
1871
            int level;
1872
            val = lduw(s->pc);
1873
            s->pc += 2;
1874
            level = ldub(s->pc++);
1875
            gen_enter(s, val, level);
1876
        }
1877
        break;
1878
    case 0xc9: /* leave */
1879
        /* XXX: exception not precise (ESP is update before potential exception) */
1880
        if (s->ss32) {
1881
            gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1882
            gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1883
        } else {
1884
            gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1885
            gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1886
        }
1887
        gen_pop_T0(s);
1888
        ot = dflag ? OT_LONG : OT_WORD;
1889
        gen_op_mov_reg_T0[ot][R_EBP]();
1890
        gen_pop_update(s);
1891
        break;
1892
    case 0x06: /* push es */
1893
    case 0x0e: /* push cs */
1894
    case 0x16: /* push ss */
1895
    case 0x1e: /* push ds */
1896
        gen_op_movl_T0_seg(b >> 3);
1897
        gen_push_T0(s);
1898
        break;
1899
    case 0x1a0: /* push fs */
1900
    case 0x1a8: /* push gs */
1901
        gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1902
        gen_push_T0(s);
1903
        break;
1904
    case 0x07: /* pop es */
1905
    case 0x17: /* pop ss */
1906
    case 0x1f: /* pop ds */
1907
        gen_pop_T0(s);
1908
        gen_movl_seg_T0(s, b >> 3);
1909
        gen_pop_update(s);
1910
        break;
1911
    case 0x1a1: /* pop fs */
1912
    case 0x1a9: /* pop gs */
1913
        gen_pop_T0(s);
1914
        gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1915
        gen_pop_update(s);
1916
        break;
1917

    
1918
        /**************************/
1919
        /* mov */
1920
    case 0x88:
1921
    case 0x89: /* mov Gv, Ev */
1922
        if ((b & 1) == 0)
1923
            ot = OT_BYTE;
1924
        else
1925
            ot = dflag ? OT_LONG : OT_WORD;
1926
        modrm = ldub(s->pc++);
1927
        reg = (modrm >> 3) & 7;
1928
        
1929
        /* generate a generic store */
1930
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1931
        break;
1932
    case 0xc6:
1933
    case 0xc7: /* mov Ev, Iv */
1934
        if ((b & 1) == 0)
1935
            ot = OT_BYTE;
1936
        else
1937
            ot = dflag ? OT_LONG : OT_WORD;
1938
        modrm = ldub(s->pc++);
1939
        mod = (modrm >> 6) & 3;
1940
        if (mod != 3)
1941
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1942
        val = insn_get(s, ot);
1943
        gen_op_movl_T0_im(val);
1944
        if (mod != 3)
1945
            gen_op_st_T0_A0[ot]();
1946
        else
1947
            gen_op_mov_reg_T0[ot][modrm & 7]();
1948
        break;
1949
    case 0x8a:
1950
    case 0x8b: /* mov 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
        
1958
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1959
        gen_op_mov_reg_T0[ot][reg]();
1960
        break;
1961
    case 0x8e: /* mov seg, Gv */
1962
        ot = dflag ? OT_LONG : OT_WORD;
1963
        modrm = ldub(s->pc++);
1964
        reg = (modrm >> 3) & 7;
1965
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1966
        if (reg >= 6 || reg == R_CS)
1967
            goto illegal_op;
1968
        gen_movl_seg_T0(s, reg);
1969
        break;
1970
    case 0x8c: /* mov Gv, seg */
1971
        ot = dflag ? OT_LONG : OT_WORD;
1972
        modrm = ldub(s->pc++);
1973
        reg = (modrm >> 3) & 7;
1974
        if (reg >= 6)
1975
            goto illegal_op;
1976
        gen_op_movl_T0_seg(reg);
1977
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1978
        break;
1979

    
1980
    case 0x1b6: /* movzbS Gv, Eb */
1981
    case 0x1b7: /* movzwS Gv, Eb */
1982
    case 0x1be: /* movsbS Gv, Eb */
1983
    case 0x1bf: /* movswS Gv, Eb */
1984
        {
1985
            int d_ot;
1986
            /* d_ot is the size of destination */
1987
            d_ot = dflag + OT_WORD;
1988
            /* ot is the size of source */
1989
            ot = (b & 1) + OT_BYTE;
1990
            modrm = ldub(s->pc++);
1991
            reg = ((modrm >> 3) & 7) + OR_EAX;
1992
            mod = (modrm >> 6) & 3;
1993
            rm = modrm & 7;
1994
            
1995
            if (mod == 3) {
1996
                gen_op_mov_TN_reg[ot][0][rm]();
1997
                switch(ot | (b & 8)) {
1998
                case OT_BYTE:
1999
                    gen_op_movzbl_T0_T0();
2000
                    break;
2001
                case OT_BYTE | 8:
2002
                    gen_op_movsbl_T0_T0();
2003
                    break;
2004
                case OT_WORD:
2005
                    gen_op_movzwl_T0_T0();
2006
                    break;
2007
                default:
2008
                case OT_WORD | 8:
2009
                    gen_op_movswl_T0_T0();
2010
                    break;
2011
                }
2012
                gen_op_mov_reg_T0[d_ot][reg]();
2013
            } else {
2014
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2015
                if (b & 8) {
2016
                    gen_op_lds_T0_A0[ot]();
2017
                } else {
2018
                    gen_op_ldu_T0_A0[ot]();
2019
                }
2020
                gen_op_mov_reg_T0[d_ot][reg]();
2021
            }
2022
        }
2023
        break;
2024

    
2025
    case 0x8d: /* lea */
2026
        ot = dflag ? OT_LONG : OT_WORD;
2027
        modrm = ldub(s->pc++);
2028
        reg = (modrm >> 3) & 7;
2029
        /* we must ensure that no segment is added */
2030
        s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS | 
2031
                       PREFIX_ES | PREFIX_FS | PREFIX_GS);
2032
        val = s->addseg;
2033
        s->addseg = 0;
2034
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2035
        s->addseg = val;
2036
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2037
        break;
2038
        
2039
    case 0xa0: /* mov EAX, Ov */
2040
    case 0xa1:
2041
    case 0xa2: /* mov Ov, EAX */
2042
    case 0xa3:
2043
        if ((b & 1) == 0)
2044
            ot = OT_BYTE;
2045
        else
2046
            ot = dflag ? OT_LONG : OT_WORD;
2047
        if (s->aflag)
2048
            offset_addr = insn_get(s, OT_LONG);
2049
        else
2050
            offset_addr = insn_get(s, OT_WORD);
2051
        gen_op_movl_A0_im(offset_addr);
2052
        /* handle override */
2053
        /* XXX: factorize that */
2054
        {
2055
            int override, must_add_seg;
2056
            override = R_DS;
2057
            must_add_seg = s->addseg;
2058
            if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | 
2059
                             PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
2060
                if (s->prefix & PREFIX_ES)
2061
                    override = R_ES;
2062
                else if (s->prefix & PREFIX_CS)
2063
                    override = R_CS;
2064
                else if (s->prefix & PREFIX_SS)
2065
                    override = R_SS;
2066
                else if (s->prefix & PREFIX_DS)
2067
                    override = R_DS;
2068
                else if (s->prefix & PREFIX_FS)
2069
                    override = R_FS;
2070
                else
2071
                    override = R_GS;
2072
                must_add_seg = 1;
2073
            }
2074
            if (must_add_seg) {
2075
                gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2076
            }
2077
        }
2078
        if ((b & 2) == 0) {
2079
            gen_op_ld_T0_A0[ot]();
2080
            gen_op_mov_reg_T0[ot][R_EAX]();
2081
        } else {
2082
            gen_op_mov_TN_reg[ot][0][R_EAX]();
2083
            gen_op_st_T0_A0[ot]();
2084
        }
2085
        break;
2086

    
2087
    case 0xb0 ... 0xb7: /* mov R, Ib */
2088
        val = insn_get(s, OT_BYTE);
2089
        gen_op_movl_T0_im(val);
2090
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2091
        break;
2092
    case 0xb8 ... 0xbf: /* mov R, Iv */
2093
        ot = dflag ? OT_LONG : OT_WORD;
2094
        val = insn_get(s, ot);
2095
        reg = OR_EAX + (b & 7);
2096
        gen_op_movl_T0_im(val);
2097
        gen_op_mov_reg_T0[ot][reg]();
2098
        break;
2099

    
2100
    case 0x91 ... 0x97: /* xchg R, EAX */
2101
        ot = dflag ? OT_LONG : OT_WORD;
2102
        reg = b & 7;
2103
        rm = R_EAX;
2104
        goto do_xchg_reg;
2105
    case 0x86:
2106
    case 0x87: /* xchg Ev, Gv */
2107
        if ((b & 1) == 0)
2108
            ot = OT_BYTE;
2109
        else
2110
            ot = dflag ? OT_LONG : OT_WORD;
2111
        modrm = ldub(s->pc++);
2112
        reg = (modrm >> 3) & 7;
2113
        mod = (modrm >> 6) & 3;
2114
        if (mod == 3) {
2115
            rm = modrm & 7;
2116
        do_xchg_reg:
2117
            gen_op_mov_TN_reg[ot][0][reg]();
2118
            gen_op_mov_TN_reg[ot][1][rm]();
2119
            gen_op_mov_reg_T0[ot][rm]();
2120
            gen_op_mov_reg_T1[ot][reg]();
2121
        } else {
2122
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2123
            gen_op_mov_TN_reg[ot][0][reg]();
2124
            gen_op_ld_T1_A0[ot]();
2125
            gen_op_st_T0_A0[ot]();
2126
            gen_op_mov_reg_T1[ot][reg]();
2127
        }
2128
        break;
2129
    case 0xc4: /* les Gv */
2130
        op = R_ES;
2131
        goto do_lxx;
2132
    case 0xc5: /* lds Gv */
2133
        op = R_DS;
2134
        goto do_lxx;
2135
    case 0x1b2: /* lss Gv */
2136
        op = R_SS;
2137
        goto do_lxx;
2138
    case 0x1b4: /* lfs Gv */
2139
        op = R_FS;
2140
        goto do_lxx;
2141
    case 0x1b5: /* lgs Gv */
2142
        op = R_GS;
2143
    do_lxx:
2144
        ot = dflag ? OT_LONG : OT_WORD;
2145
        modrm = ldub(s->pc++);
2146
        reg = (modrm >> 3) & 7;
2147
        mod = (modrm >> 6) & 3;
2148
        if (mod == 3)
2149
            goto illegal_op;
2150
        gen_op_ld_T1_A0[ot]();
2151
        gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2152
        /* load the segment first to handle exceptions properly */
2153
        gen_op_lduw_T0_A0();
2154
        gen_movl_seg_T0(s, op);
2155
        /* then put the data */
2156
        gen_op_mov_reg_T1[ot][reg]();
2157
        break;
2158
        
2159
        /************************/
2160
        /* shifts */
2161
    case 0xc0:
2162
    case 0xc1:
2163
        /* shift Ev,Ib */
2164
        shift = 2;
2165
    grp2:
2166
        {
2167
            if ((b & 1) == 0)
2168
                ot = OT_BYTE;
2169
            else
2170
                ot = dflag ? OT_LONG : OT_WORD;
2171
            
2172
            modrm = ldub(s->pc++);
2173
            mod = (modrm >> 6) & 3;
2174
            rm = modrm & 7;
2175
            op = (modrm >> 3) & 7;
2176
            
2177
            if (mod != 3) {
2178
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2179
                gen_op_ld_T0_A0[ot]();
2180
                opreg = OR_TMP0;
2181
            } else {
2182
                opreg = rm + OR_EAX;
2183
            }
2184

    
2185
            /* simpler op */
2186
            if (shift == 0) {
2187
                gen_shift(s, op, ot, opreg, OR_ECX);
2188
            } else {
2189
                if (shift == 2) {
2190
                    shift = ldub(s->pc++);
2191
                }
2192
                gen_shifti(s, op, ot, opreg, shift);
2193
            }
2194

    
2195
            if (mod != 3) {
2196
                gen_op_st_T0_A0[ot]();
2197
            }
2198
        }
2199
        break;
2200
    case 0xd0:
2201
    case 0xd1:
2202
        /* shift Ev,1 */
2203
        shift = 1;
2204
        goto grp2;
2205
    case 0xd2:
2206
    case 0xd3:
2207
        /* shift Ev,cl */
2208
        shift = 0;
2209
        goto grp2;
2210

    
2211
    case 0x1a4: /* shld imm */
2212
        op = 0;
2213
        shift = 1;
2214
        goto do_shiftd;
2215
    case 0x1a5: /* shld cl */
2216
        op = 0;
2217
        shift = 0;
2218
        goto do_shiftd;
2219
    case 0x1ac: /* shrd imm */
2220
        op = 1;
2221
        shift = 1;
2222
        goto do_shiftd;
2223
    case 0x1ad: /* shrd cl */
2224
        op = 1;
2225
        shift = 0;
2226
    do_shiftd:
2227
        ot = dflag ? OT_LONG : OT_WORD;
2228
        modrm = ldub(s->pc++);
2229
        mod = (modrm >> 6) & 3;
2230
        rm = modrm & 7;
2231
        reg = (modrm >> 3) & 7;
2232
        
2233
        if (mod != 3) {
2234
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2235
            gen_op_ld_T0_A0[ot]();
2236
        } else {
2237
            gen_op_mov_TN_reg[ot][0][rm]();
2238
        }
2239
        gen_op_mov_TN_reg[ot][1][reg]();
2240
        
2241
        if (shift) {
2242
            val = ldub(s->pc++);
2243
            val &= 0x1f;
2244
            if (val) {
2245
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2246
                if (op == 0 && ot != OT_WORD)
2247
                    s->cc_op = CC_OP_SHLB + ot;
2248
                else
2249
                    s->cc_op = CC_OP_SARB + ot;
2250
            }
2251
        } else {
2252
            if (s->cc_op != CC_OP_DYNAMIC)
2253
                gen_op_set_cc_op(s->cc_op);
2254
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2255
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2256
        }
2257
        if (mod != 3) {
2258
            gen_op_st_T0_A0[ot]();
2259
        } else {
2260
            gen_op_mov_reg_T0[ot][rm]();
2261
        }
2262
        break;
2263

    
2264
        /************************/
2265
        /* floats */
2266
    case 0xd8 ... 0xdf: 
2267
        modrm = ldub(s->pc++);
2268
        mod = (modrm >> 6) & 3;
2269
        rm = modrm & 7;
2270
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2271
        
2272
        if (mod != 3) {
2273
            /* memory op */
2274
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2275
            switch(op) {
2276
            case 0x00 ... 0x07: /* fxxxs */
2277
            case 0x10 ... 0x17: /* fixxxl */
2278
            case 0x20 ... 0x27: /* fxxxl */
2279
            case 0x30 ... 0x37: /* fixxx */
2280
                {
2281
                    int op1;
2282
                    op1 = op & 7;
2283

    
2284
                    switch(op >> 4) {
2285
                    case 0:
2286
                        gen_op_flds_FT0_A0();
2287
                        break;
2288
                    case 1:
2289
                        gen_op_fildl_FT0_A0();
2290
                        break;
2291
                    case 2:
2292
                        gen_op_fldl_FT0_A0();
2293
                        break;
2294
                    case 3:
2295
                    default:
2296
                        gen_op_fild_FT0_A0();
2297
                        break;
2298
                    }
2299
                    
2300
                    gen_op_fp_arith_ST0_FT0[op1]();
2301
                    if (op1 == 3) {
2302
                        /* fcomp needs pop */
2303
                        gen_op_fpop();
2304
                    }
2305
                }
2306
                break;
2307
            case 0x08: /* flds */
2308
            case 0x0a: /* fsts */
2309
            case 0x0b: /* fstps */
2310
            case 0x18: /* fildl */
2311
            case 0x1a: /* fistl */
2312
            case 0x1b: /* fistpl */
2313
            case 0x28: /* fldl */
2314
            case 0x2a: /* fstl */
2315
            case 0x2b: /* fstpl */
2316
            case 0x38: /* filds */
2317
            case 0x3a: /* fists */
2318
            case 0x3b: /* fistps */
2319
                
2320
                switch(op & 7) {
2321
                case 0:
2322
                    gen_op_fpush();
2323
                    switch(op >> 4) {
2324
                    case 0:
2325
                        gen_op_flds_ST0_A0();
2326
                        break;
2327
                    case 1:
2328
                        gen_op_fildl_ST0_A0();
2329
                        break;
2330
                    case 2:
2331
                        gen_op_fldl_ST0_A0();
2332
                        break;
2333
                    case 3:
2334
                    default:
2335
                        gen_op_fild_ST0_A0();
2336
                        break;
2337
                    }
2338
                    break;
2339
                default:
2340
                    switch(op >> 4) {
2341
                    case 0:
2342
                        gen_op_fsts_ST0_A0();
2343
                        break;
2344
                    case 1:
2345
                        gen_op_fistl_ST0_A0();
2346
                        break;
2347
                    case 2:
2348
                        gen_op_fstl_ST0_A0();
2349
                        break;
2350
                    case 3:
2351
                    default:
2352
                        gen_op_fist_ST0_A0();
2353
                        break;
2354
                    }
2355
                    if ((op & 7) == 3)
2356
                        gen_op_fpop();
2357
                    break;
2358
                }
2359
                break;
2360
            case 0x0d: /* fldcw mem */
2361
                gen_op_fldcw_A0();
2362
                break;
2363
            case 0x0f: /* fnstcw mem */
2364
                gen_op_fnstcw_A0();
2365
                break;
2366
            case 0x1d: /* fldt mem */
2367
                gen_op_fpush();
2368
                gen_op_fldt_ST0_A0();
2369
                break;
2370
            case 0x1f: /* fstpt mem */
2371
                gen_op_fstt_ST0_A0();
2372
                gen_op_fpop();
2373
                break;
2374
            case 0x2f: /* fnstsw mem */
2375
                gen_op_fnstsw_A0();
2376
                break;
2377
            case 0x3c: /* fbld */
2378
                gen_op_fpush();
2379
                gen_op_fbld_ST0_A0();
2380
                break;
2381
            case 0x3e: /* fbstp */
2382
                gen_op_fbst_ST0_A0();
2383
                gen_op_fpop();
2384
                break;
2385
            case 0x3d: /* fildll */
2386
                gen_op_fpush();
2387
                gen_op_fildll_ST0_A0();
2388
                break;
2389
            case 0x3f: /* fistpll */
2390
                gen_op_fistll_ST0_A0();
2391
                gen_op_fpop();
2392
                break;
2393
            default:
2394
                goto illegal_op;
2395
            }
2396
        } else {
2397
            /* register float ops */
2398
            opreg = rm;
2399

    
2400
            switch(op) {
2401
            case 0x08: /* fld sti */
2402
                gen_op_fpush();
2403
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
2404
                break;
2405
            case 0x09: /* fxchg sti */
2406
                gen_op_fxchg_ST0_STN(opreg);
2407
                break;
2408
            case 0x0a: /* grp d9/2 */
2409
                switch(rm) {
2410
                case 0: /* fnop */
2411
                    break;
2412
                default:
2413
                    goto illegal_op;
2414
                }
2415
                break;
2416
            case 0x0c: /* grp d9/4 */
2417
                switch(rm) {
2418
                case 0: /* fchs */
2419
                    gen_op_fchs_ST0();
2420
                    break;
2421
                case 1: /* fabs */
2422
                    gen_op_fabs_ST0();
2423
                    break;
2424
                case 4: /* ftst */
2425
                    gen_op_fldz_FT0();
2426
                    gen_op_fcom_ST0_FT0();
2427
                    break;
2428
                case 5: /* fxam */
2429
                    gen_op_fxam_ST0();
2430
                    break;
2431
                default:
2432
                    goto illegal_op;
2433
                }
2434
                break;
2435
            case 0x0d: /* grp d9/5 */
2436
                {
2437
                    switch(rm) {
2438
                    case 0:
2439
                        gen_op_fpush();
2440
                        gen_op_fld1_ST0();
2441
                        break;
2442
                    case 1:
2443
                        gen_op_fpush();
2444
                        gen_op_fldl2t_ST0();
2445
                        break;
2446
                    case 2:
2447
                        gen_op_fpush();
2448
                        gen_op_fldl2e_ST0();
2449
                        break;
2450
                    case 3:
2451
                        gen_op_fpush();
2452
                        gen_op_fldpi_ST0();
2453
                        break;
2454
                    case 4:
2455
                        gen_op_fpush();
2456
                        gen_op_fldlg2_ST0();
2457
                        break;
2458
                    case 5:
2459
                        gen_op_fpush();
2460
                        gen_op_fldln2_ST0();
2461
                        break;
2462
                    case 6:
2463
                        gen_op_fpush();
2464
                        gen_op_fldz_ST0();
2465
                        break;
2466
                    default:
2467
                        goto illegal_op;
2468
                    }
2469
                }
2470
                break;
2471
            case 0x0e: /* grp d9/6 */
2472
                switch(rm) {
2473
                case 0: /* f2xm1 */
2474
                    gen_op_f2xm1();
2475
                    break;
2476
                case 1: /* fyl2x */
2477
                    gen_op_fyl2x();
2478
                    break;
2479
                case 2: /* fptan */
2480
                    gen_op_fptan();
2481
                    break;
2482
                case 3: /* fpatan */
2483
                    gen_op_fpatan();
2484
                    break;
2485
                case 4: /* fxtract */
2486
                    gen_op_fxtract();
2487
                    break;
2488
                case 5: /* fprem1 */
2489
                    gen_op_fprem1();
2490
                    break;
2491
                case 6: /* fdecstp */
2492
                    gen_op_fdecstp();
2493
                    break;
2494
                default:
2495
                case 7: /* fincstp */
2496
                    gen_op_fincstp();
2497
                    break;
2498
                }
2499
                break;
2500
            case 0x0f: /* grp d9/7 */
2501
                switch(rm) {
2502
                case 0: /* fprem */
2503
                    gen_op_fprem();
2504
                    break;
2505
                case 1: /* fyl2xp1 */
2506
                    gen_op_fyl2xp1();
2507
                    break;
2508
                case 2: /* fsqrt */
2509
                    gen_op_fsqrt();
2510
                    break;
2511
                case 3: /* fsincos */
2512
                    gen_op_fsincos();
2513
                    break;
2514
                case 5: /* fscale */
2515
                    gen_op_fscale();
2516
                    break;
2517
                case 4: /* frndint */
2518
                    gen_op_frndint();
2519
                    break;
2520
                case 6: /* fsin */
2521
                    gen_op_fsin();
2522
                    break;
2523
                default:
2524
                case 7: /* fcos */
2525
                    gen_op_fcos();
2526
                    break;
2527
                }
2528
                break;
2529
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2530
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2531
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2532
                {
2533
                    int op1;
2534
                    
2535
                    op1 = op & 7;
2536
                    if (op >= 0x20) {
2537
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2538
                        if (op >= 0x30)
2539
                            gen_op_fpop();
2540
                    } else {
2541
                        gen_op_fmov_FT0_STN(opreg);
2542
                        gen_op_fp_arith_ST0_FT0[op1]();
2543
                    }
2544
                }
2545
                break;
2546
            case 0x02: /* fcom */
2547
                gen_op_fmov_FT0_STN(opreg);
2548
                gen_op_fcom_ST0_FT0();
2549
                break;
2550
            case 0x03: /* fcomp */
2551
                gen_op_fmov_FT0_STN(opreg);
2552
                gen_op_fcom_ST0_FT0();
2553
                gen_op_fpop();
2554
                break;
2555
            case 0x15: /* da/5 */
2556
                switch(rm) {
2557
                case 1: /* fucompp */
2558
                    gen_op_fmov_FT0_STN(1);
2559
                    gen_op_fucom_ST0_FT0();
2560
                    gen_op_fpop();
2561
                    gen_op_fpop();
2562
                    break;
2563
                default:
2564
                    goto illegal_op;
2565
                }
2566
                break;
2567
            case 0x1c:
2568
                switch(rm) {
2569
                case 2: /* fclex */
2570
                    gen_op_fclex();
2571
                    break;
2572
                case 3: /* fninit */
2573
                    gen_op_fninit();
2574
                    break;
2575
                default:
2576
                    goto illegal_op;
2577
                }
2578
                break;
2579
            case 0x2a: /* fst sti */
2580
                gen_op_fmov_STN_ST0(opreg);
2581
                break;
2582
            case 0x2b: /* fstp sti */
2583
                gen_op_fmov_STN_ST0(opreg);
2584
                gen_op_fpop();
2585
                break;
2586
            case 0x2c: /* fucom st(i) */
2587
                gen_op_fmov_FT0_STN(opreg);
2588
                gen_op_fucom_ST0_FT0();
2589
                break;
2590
            case 0x2d: /* fucomp st(i) */
2591
                gen_op_fmov_FT0_STN(opreg);
2592
                gen_op_fucom_ST0_FT0();
2593
                gen_op_fpop();
2594
                break;
2595
            case 0x33: /* de/3 */
2596
                switch(rm) {
2597
                case 1: /* fcompp */
2598
                    gen_op_fmov_FT0_STN(1);
2599
                    gen_op_fcom_ST0_FT0();
2600
                    gen_op_fpop();
2601
                    gen_op_fpop();
2602
                    break;
2603
                default:
2604
                    goto illegal_op;
2605
                }
2606
                break;
2607
            case 0x3c: /* df/4 */
2608
                switch(rm) {
2609
                case 0:
2610
                    gen_op_fnstsw_EAX();
2611
                    break;
2612
                default:
2613
                    goto illegal_op;
2614
                }
2615
                break;
2616
            default:
2617
                goto illegal_op;
2618
            }
2619
        }
2620
        break;
2621
        /************************/
2622
        /* string ops */
2623
    case 0xa4: /* movsS */
2624
    case 0xa5:
2625
        if ((b & 1) == 0)
2626
            ot = OT_BYTE;
2627
        else
2628
            ot = dflag ? OT_LONG : OT_WORD;
2629
        if (prefixes & PREFIX_REPZ) {
2630
            gen_op_movs[3 + ot]();
2631
        } else {
2632
            gen_op_movs[ot]();
2633
        }
2634
        break;
2635
        
2636
    case 0xaa: /* stosS */
2637
    case 0xab:
2638
        if ((b & 1) == 0)
2639
            ot = OT_BYTE;
2640
        else
2641
            ot = dflag ? OT_LONG : OT_WORD;
2642
        if (prefixes & PREFIX_REPZ) {
2643
            gen_op_stos[3 + ot]();
2644
        } else {
2645
            gen_op_stos[ot]();
2646
        }
2647
        break;
2648
    case 0xac: /* lodsS */
2649
    case 0xad:
2650
        if ((b & 1) == 0)
2651
            ot = OT_BYTE;
2652
        else
2653
            ot = dflag ? OT_LONG : OT_WORD;
2654
        if (prefixes & PREFIX_REPZ) {
2655
            gen_op_lods[3 + ot]();
2656
        } else {
2657
            gen_op_lods[ot]();
2658
        }
2659
        break;
2660
    case 0xae: /* scasS */
2661
    case 0xaf:
2662
        if ((b & 1) == 0)
2663
            ot = OT_BYTE;
2664
        else
2665
            ot = dflag ? OT_LONG : OT_WORD;
2666
        if (prefixes & PREFIX_REPNZ) {
2667
            if (s->cc_op != CC_OP_DYNAMIC)
2668
                gen_op_set_cc_op(s->cc_op);
2669
            gen_op_scas[6 + ot]();
2670
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2671
        } else if (prefixes & PREFIX_REPZ) {
2672
            if (s->cc_op != CC_OP_DYNAMIC)
2673
                gen_op_set_cc_op(s->cc_op);
2674
            gen_op_scas[3 + ot]();
2675
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2676
        } else {
2677
            gen_op_scas[ot]();
2678
            s->cc_op = CC_OP_SUBB + ot;
2679
        }
2680
        break;
2681

    
2682
    case 0xa6: /* cmpsS */
2683
    case 0xa7:
2684
        if ((b & 1) == 0)
2685
            ot = OT_BYTE;
2686
        else
2687
            ot = dflag ? OT_LONG : OT_WORD;
2688
        if (prefixes & PREFIX_REPNZ) {
2689
            if (s->cc_op != CC_OP_DYNAMIC)
2690
                gen_op_set_cc_op(s->cc_op);
2691
            gen_op_cmps[6 + ot]();
2692
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2693
        } else if (prefixes & PREFIX_REPZ) {
2694
            if (s->cc_op != CC_OP_DYNAMIC)
2695
                gen_op_set_cc_op(s->cc_op);
2696
            gen_op_cmps[3 + ot]();
2697
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2698
        } else {
2699
            gen_op_cmps[ot]();
2700
            s->cc_op = CC_OP_SUBB + ot;
2701
        }
2702
        break;
2703
        
2704
        /************************/
2705
        /* port I/O */
2706
    case 0x6c: /* insS */
2707
    case 0x6d:
2708
        if ((b & 1) == 0)
2709
            ot = OT_BYTE;
2710
        else
2711
            ot = dflag ? OT_LONG : OT_WORD;
2712
        if (prefixes & PREFIX_REPZ) {
2713
            gen_op_ins[3 + ot]();
2714
        } else {
2715
            gen_op_ins[ot]();
2716
        }
2717
        break;
2718
    case 0x6e: /* outsS */
2719
    case 0x6f:
2720
        if ((b & 1) == 0)
2721
            ot = OT_BYTE;
2722
        else
2723
            ot = dflag ? OT_LONG : OT_WORD;
2724
        if (prefixes & PREFIX_REPZ) {
2725
            gen_op_outs[3 + ot]();
2726
        } else {
2727
            gen_op_outs[ot]();
2728
        }
2729
        break;
2730
    case 0xe4:
2731
    case 0xe5:
2732
        if ((b & 1) == 0)
2733
            ot = OT_BYTE;
2734
        else
2735
            ot = dflag ? OT_LONG : OT_WORD;
2736
        val = ldub(s->pc++);
2737
        gen_op_movl_T0_im(val);
2738
        gen_op_in[ot]();
2739
        gen_op_mov_reg_T1[ot][R_EAX]();
2740
        break;
2741
    case 0xe6:
2742
    case 0xe7:
2743
        if ((b & 1) == 0)
2744
            ot = OT_BYTE;
2745
        else
2746
            ot = dflag ? OT_LONG : OT_WORD;
2747
        val = ldub(s->pc++);
2748
        gen_op_movl_T0_im(val);
2749
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2750
        gen_op_out[ot]();
2751
        break;
2752
    case 0xec:
2753
    case 0xed:
2754
        if ((b & 1) == 0)
2755
            ot = OT_BYTE;
2756
        else
2757
            ot = dflag ? OT_LONG : OT_WORD;
2758
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2759
        gen_op_in[ot]();
2760
        gen_op_mov_reg_T1[ot][R_EAX]();
2761
        break;
2762
    case 0xee:
2763
    case 0xef:
2764
        if ((b & 1) == 0)
2765
            ot = OT_BYTE;
2766
        else
2767
            ot = dflag ? OT_LONG : OT_WORD;
2768
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2769
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2770
        gen_op_out[ot]();
2771
        break;
2772

    
2773
        /************************/
2774
        /* control */
2775
    case 0xc2: /* ret im */
2776
        val = ldsw(s->pc);
2777
        s->pc += 2;
2778
        gen_pop_T0(s);
2779
        if (s->ss32)
2780
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2781
        else
2782
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2783
        if (s->dflag == 0)
2784
            gen_op_andl_T0_ffff();
2785
        gen_op_jmp_T0();
2786
        s->is_jmp = 1;
2787
        break;
2788
    case 0xc3: /* ret */
2789
        gen_pop_T0(s);
2790
        gen_pop_update(s);
2791
        if (s->dflag == 0)
2792
            gen_op_andl_T0_ffff();
2793
        gen_op_jmp_T0();
2794
        s->is_jmp = 1;
2795
        break;
2796
    case 0xca: /* lret im */
2797
        val = ldsw(s->pc);
2798
        s->pc += 2;
2799
        /* pop offset */
2800
        gen_pop_T0(s);
2801
        if (s->dflag == 0)
2802
            gen_op_andl_T0_ffff();
2803
        gen_op_jmp_T0();
2804
        gen_pop_update(s);
2805
        /* pop selector */
2806
        gen_pop_T0(s);
2807
        gen_movl_seg_T0(s, R_CS);
2808
        gen_pop_update(s);
2809
        /* add stack offset */
2810
        if (s->ss32)
2811
            gen_op_addl_ESP_im(val + (2 << s->dflag));
2812
        else
2813
            gen_op_addw_ESP_im(val + (2 << s->dflag));
2814
        s->is_jmp = 1;
2815
        break;
2816
    case 0xcb: /* lret */
2817
        /* pop offset */
2818
        gen_pop_T0(s);
2819
        if (s->dflag == 0)
2820
            gen_op_andl_T0_ffff();
2821
        gen_op_jmp_T0();
2822
        gen_pop_update(s);
2823
        /* pop selector */
2824
        gen_pop_T0(s);
2825
        gen_movl_seg_T0(s, R_CS);
2826
        gen_pop_update(s);
2827
        s->is_jmp = 1;
2828
        break;
2829
    case 0xe8: /* call im */
2830
        {
2831
            unsigned int next_eip;
2832
            ot = dflag ? OT_LONG : OT_WORD;
2833
            val = insn_get(s, ot);
2834
            next_eip = s->pc - s->cs_base;
2835
            val += next_eip;
2836
            if (s->dflag == 0)
2837
                val &= 0xffff;
2838
            gen_op_movl_T0_im(next_eip);
2839
            gen_push_T0(s);
2840
            gen_op_jmp_im(val);
2841
            s->is_jmp = 1;
2842
        }
2843
        break;
2844
    case 0x9a: /* lcall im */
2845
        {
2846
            unsigned int selector, offset;
2847

    
2848
            ot = dflag ? OT_LONG : OT_WORD;
2849
            offset = insn_get(s, ot);
2850
            selector = insn_get(s, OT_WORD);
2851
            
2852
            /* push return segment + offset */
2853
            gen_op_movl_T0_seg(R_CS);
2854
            gen_push_T0(s);
2855
            next_eip = s->pc - s->cs_base;
2856
            gen_op_movl_T0_im(next_eip);
2857
            gen_push_T0(s);
2858

    
2859
            /* change cs and pc */
2860
            gen_op_movl_T0_im(selector);
2861
            gen_movl_seg_T0(s, R_CS);
2862
            gen_op_jmp_im((unsigned long)offset);
2863
            s->is_jmp = 1;
2864
        }
2865
        break;
2866
    case 0xe9: /* jmp */
2867
        ot = dflag ? OT_LONG : OT_WORD;
2868
        val = insn_get(s, ot);
2869
        val += s->pc - s->cs_base;
2870
        if (s->dflag == 0)
2871
            val = val & 0xffff;
2872
        gen_op_jmp_im(val);
2873
        s->is_jmp = 1;
2874
        break;
2875
    case 0xea: /* ljmp im */
2876
        {
2877
            unsigned int selector, offset;
2878

    
2879
            ot = dflag ? OT_LONG : OT_WORD;
2880
            offset = insn_get(s, ot);
2881
            selector = insn_get(s, OT_WORD);
2882
            
2883
            /* change cs and pc */
2884
            gen_op_movl_T0_im(selector);
2885
            gen_movl_seg_T0(s, R_CS);
2886
            gen_op_jmp_im((unsigned long)offset);
2887
            s->is_jmp = 1;
2888
        }
2889
        break;
2890
    case 0xeb: /* jmp Jb */
2891
        val = (int8_t)insn_get(s, OT_BYTE);
2892
        val += s->pc - s->cs_base;
2893
        if (s->dflag == 0)
2894
            val = val & 0xffff;
2895
        gen_op_jmp_im(val);
2896
        s->is_jmp = 1;
2897
        break;
2898
    case 0x70 ... 0x7f: /* jcc Jb */
2899
        val = (int8_t)insn_get(s, OT_BYTE);
2900
        goto do_jcc;
2901
    case 0x180 ... 0x18f: /* jcc Jv */
2902
        if (dflag) {
2903
            val = insn_get(s, OT_LONG);
2904
        } else {
2905
            val = (int16_t)insn_get(s, OT_WORD); 
2906
        }
2907
    do_jcc:
2908
        next_eip = s->pc - s->cs_base;
2909
        val += next_eip;
2910
        if (s->dflag == 0)
2911
            val &= 0xffff;
2912
        gen_jcc(s, b, val, next_eip);
2913
        s->is_jmp = 1;
2914
        break;
2915

    
2916
    case 0x190 ... 0x19f: /* setcc Gv */
2917
        modrm = ldub(s->pc++);
2918
        gen_setcc(s, b);
2919
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2920
        break;
2921
    case 0x140 ... 0x14f: /* cmov Gv, Ev */
2922
        ot = dflag ? OT_LONG : OT_WORD;
2923
        modrm = ldub(s->pc++);
2924
        reg = (modrm >> 3) & 7;
2925
        mod = (modrm >> 6) & 3;
2926
        gen_setcc(s, b);
2927
        if (mod != 3) {
2928
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2929
            gen_op_ld_T1_A0[ot]();
2930
        } else {
2931
            rm = modrm & 7;
2932
            gen_op_mov_TN_reg[ot][1][rm]();
2933
        }
2934
        gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
2935
        break;
2936
        
2937
        /************************/
2938
        /* flags */
2939
    case 0x9c: /* pushf */
2940
        if (s->cc_op != CC_OP_DYNAMIC)
2941
            gen_op_set_cc_op(s->cc_op);
2942
        gen_op_movl_T0_eflags();
2943
        gen_push_T0(s);
2944
        break;
2945
    case 0x9d: /* popf */
2946
        gen_pop_T0(s);
2947
        gen_op_movl_eflags_T0();
2948
        gen_pop_update(s);
2949
        s->cc_op = CC_OP_EFLAGS;
2950
        break;
2951
    case 0x9e: /* sahf */
2952
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2953
        if (s->cc_op != CC_OP_DYNAMIC)
2954
            gen_op_set_cc_op(s->cc_op);
2955
        gen_op_movb_eflags_T0();
2956
        s->cc_op = CC_OP_EFLAGS;
2957
        break;
2958
    case 0x9f: /* lahf */
2959
        if (s->cc_op != CC_OP_DYNAMIC)
2960
            gen_op_set_cc_op(s->cc_op);
2961
        gen_op_movl_T0_eflags();
2962
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2963
        break;
2964
    case 0xf5: /* cmc */
2965
        if (s->cc_op != CC_OP_DYNAMIC)
2966
            gen_op_set_cc_op(s->cc_op);
2967
        gen_op_cmc();
2968
        s->cc_op = CC_OP_EFLAGS;
2969
        break;
2970
    case 0xf8: /* clc */
2971
        if (s->cc_op != CC_OP_DYNAMIC)
2972
            gen_op_set_cc_op(s->cc_op);
2973
        gen_op_clc();
2974
        s->cc_op = CC_OP_EFLAGS;
2975
        break;
2976
    case 0xf9: /* stc */
2977
        if (s->cc_op != CC_OP_DYNAMIC)
2978
            gen_op_set_cc_op(s->cc_op);
2979
        gen_op_stc();
2980
        s->cc_op = CC_OP_EFLAGS;
2981
        break;
2982
    case 0xfc: /* cld */
2983
        gen_op_cld();
2984
        break;
2985
    case 0xfd: /* std */
2986
        gen_op_std();
2987
        break;
2988

    
2989
        /************************/
2990
        /* bit operations */
2991
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
2992
        ot = dflag ? OT_LONG : OT_WORD;
2993
        modrm = ldub(s->pc++);
2994
        op = (modrm >> 3) & 7;
2995
        mod = (modrm >> 6) & 3;
2996
        rm = modrm & 7;
2997
        if (mod != 3) {
2998
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2999
            gen_op_ld_T0_A0[ot]();
3000
        } else {
3001
            gen_op_mov_TN_reg[ot][0][rm]();
3002
        }
3003
        /* load shift */
3004
        val = ldub(s->pc++);
3005
        gen_op_movl_T1_im(val);
3006
        if (op < 4)
3007
            goto illegal_op;
3008
        op -= 4;
3009
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3010
        s->cc_op = CC_OP_SARB + ot;
3011
        if (op != 0) {
3012
            if (mod != 3)
3013
                gen_op_st_T0_A0[ot]();
3014
            else
3015
                gen_op_mov_reg_T0[ot][rm]();
3016
        }
3017
        break;
3018
    case 0x1a3: /* bt Gv, Ev */
3019
        op = 0;
3020
        goto do_btx;
3021
    case 0x1ab: /* bts */
3022
        op = 1;
3023
        goto do_btx;
3024
    case 0x1b3: /* btr */
3025
        op = 2;
3026
        goto do_btx;
3027
    case 0x1bb: /* btc */
3028
        op = 3;
3029
    do_btx:
3030
        ot = dflag ? OT_LONG : OT_WORD;
3031
        modrm = ldub(s->pc++);
3032
        reg = (modrm >> 3) & 7;
3033
        mod = (modrm >> 6) & 3;
3034
        rm = modrm & 7;
3035
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
3036
        if (mod != 3) {
3037
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3038
            /* specific case: we need to add a displacement */
3039
            if (ot == OT_WORD)
3040
                gen_op_add_bitw_A0_T1();
3041
            else
3042
                gen_op_add_bitl_A0_T1();
3043
            gen_op_ld_T0_A0[ot]();
3044
        } else {
3045
            gen_op_mov_TN_reg[ot][0][rm]();
3046
        }
3047
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3048
        s->cc_op = CC_OP_SARB + ot;
3049
        if (op != 0) {
3050
            if (mod != 3)
3051
                gen_op_st_T0_A0[ot]();
3052
            else
3053
                gen_op_mov_reg_T0[ot][rm]();
3054
        }
3055
        break;
3056
    case 0x1bc: /* bsf */
3057
    case 0x1bd: /* bsr */
3058
        ot = dflag ? OT_LONG : OT_WORD;
3059
        modrm = ldub(s->pc++);
3060
        reg = (modrm >> 3) & 7;
3061
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3062
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3063
        /* NOTE: we always write back the result. Intel doc says it is
3064
           undefined if T0 == 0 */
3065
        gen_op_mov_reg_T0[ot][reg]();
3066
        s->cc_op = CC_OP_LOGICB + ot;
3067
        break;
3068
        /************************/
3069
        /* bcd */
3070
    case 0x27: /* daa */
3071
        if (s->cc_op != CC_OP_DYNAMIC)
3072
            gen_op_set_cc_op(s->cc_op);
3073
        gen_op_daa();
3074
        s->cc_op = CC_OP_EFLAGS;
3075
        break;
3076
    case 0x2f: /* das */
3077
        if (s->cc_op != CC_OP_DYNAMIC)
3078
            gen_op_set_cc_op(s->cc_op);
3079
        gen_op_das();
3080
        s->cc_op = CC_OP_EFLAGS;
3081
        break;
3082
    case 0x37: /* aaa */
3083
        if (s->cc_op != CC_OP_DYNAMIC)
3084
            gen_op_set_cc_op(s->cc_op);
3085
        gen_op_aaa();
3086
        s->cc_op = CC_OP_EFLAGS;
3087
        break;
3088
    case 0x3f: /* aas */
3089
        if (s->cc_op != CC_OP_DYNAMIC)
3090
            gen_op_set_cc_op(s->cc_op);
3091
        gen_op_aas();
3092
        s->cc_op = CC_OP_EFLAGS;
3093
        break;
3094
    case 0xd4: /* aam */
3095
        val = ldub(s->pc++);
3096
        gen_op_aam(val);
3097
        s->cc_op = CC_OP_LOGICB;
3098
        break;
3099
    case 0xd5: /* aad */
3100
        val = ldub(s->pc++);
3101
        gen_op_aad(val);
3102
        s->cc_op = CC_OP_LOGICB;
3103
        break;
3104
        /************************/
3105
        /* misc */
3106
    case 0x90: /* nop */
3107
        break;
3108
    case 0xcc: /* int3 */
3109
        gen_op_int3((long)pc_start);
3110
        s->is_jmp = 1;
3111
        break;
3112
    case 0xcd: /* int N */
3113
        val = ldub(s->pc++);
3114
        /* XXX: currently we ignore the interrupt number */
3115
        gen_op_int_im((long)pc_start);
3116
        s->is_jmp = 1;
3117
        break;
3118
    case 0xce: /* into */
3119
        if (s->cc_op != CC_OP_DYNAMIC)
3120
            gen_op_set_cc_op(s->cc_op);
3121
        gen_op_into((long)pc_start, (long)s->pc);
3122
        s->is_jmp = 1;
3123
        break;
3124
    case 0x1c8 ... 0x1cf: /* bswap reg */
3125
        reg = b & 7;
3126
        gen_op_mov_TN_reg[OT_LONG][0][reg]();
3127
        gen_op_bswapl_T0();
3128
        gen_op_mov_reg_T0[OT_LONG][reg]();
3129
        break;
3130
    case 0xd6: /* salc */
3131
        if (s->cc_op != CC_OP_DYNAMIC)
3132
            gen_op_set_cc_op(s->cc_op);
3133
        gen_op_salc();
3134
        break;
3135
    case 0xe0: /* loopnz */
3136
    case 0xe1: /* loopz */
3137
        if (s->cc_op != CC_OP_DYNAMIC)
3138
            gen_op_set_cc_op(s->cc_op);
3139
        /* FALL THRU */
3140
    case 0xe2: /* loop */
3141
    case 0xe3: /* jecxz */
3142
        val = (int8_t)insn_get(s, OT_BYTE);
3143
        next_eip = s->pc - s->cs_base;
3144
        val += next_eip;
3145
        if (s->dflag == 0)
3146
            val &= 0xffff;
3147
        gen_op_loop[s->aflag][b & 3](val, next_eip);
3148
        s->is_jmp = 1;
3149
        break;
3150
    case 0x131: /* rdtsc */
3151
        gen_op_rdtsc();
3152
        break;
3153
#if 0
3154
    case 0x1a2: /* cpuid */
3155
        gen_insn0(OP_ASM);
3156
        break;
3157
#endif
3158
    default:
3159
        goto illegal_op;
3160
    }
3161
    /* lock generation */
3162
    if (s->prefix & PREFIX_LOCK)
3163
        gen_op_unlock();
3164
    return (long)s->pc;
3165
 illegal_op:
3166
    /* XXX: ensure that no lock was generated */
3167
    return -1;
3168
}
3169

    
3170
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3171
#define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3172

    
3173
/* flags read by an operation */
3174
static uint16_t opc_read_flags[NB_OPS] = { 
3175
    [INDEX_op_aas] = CC_A,
3176
    [INDEX_op_aaa] = CC_A,
3177
    [INDEX_op_das] = CC_A | CC_C,
3178
    [INDEX_op_daa] = CC_A | CC_C,
3179

    
3180
    [INDEX_op_adcb_T0_T1_cc] = CC_C,
3181
    [INDEX_op_adcw_T0_T1_cc] = CC_C,
3182
    [INDEX_op_adcl_T0_T1_cc] = CC_C,
3183
    [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3184
    [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3185
    [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3186

    
3187
    [INDEX_op_into] = CC_O,
3188

    
3189
    [INDEX_op_jo_cc] = CC_O,
3190
    [INDEX_op_jb_cc] = CC_C,
3191
    [INDEX_op_jz_cc] = CC_Z,
3192
    [INDEX_op_jbe_cc] = CC_Z | CC_C,
3193
    [INDEX_op_js_cc] = CC_S,
3194
    [INDEX_op_jp_cc] = CC_P,
3195
    [INDEX_op_jl_cc] = CC_O | CC_S,
3196
    [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3197

    
3198
    [INDEX_op_jb_subb] = CC_C,
3199
    [INDEX_op_jb_subw] = CC_C,
3200
    [INDEX_op_jb_subl] = CC_C,
3201

    
3202
    [INDEX_op_jz_subb] = CC_Z,
3203
    [INDEX_op_jz_subw] = CC_Z,
3204
    [INDEX_op_jz_subl] = CC_Z,
3205

    
3206
    [INDEX_op_jbe_subb] = CC_Z | CC_C,
3207
    [INDEX_op_jbe_subw] = CC_Z | CC_C,
3208
    [INDEX_op_jbe_subl] = CC_Z | CC_C,
3209

    
3210
    [INDEX_op_js_subb] = CC_S,
3211
    [INDEX_op_js_subw] = CC_S,
3212
    [INDEX_op_js_subl] = CC_S,
3213

    
3214
    [INDEX_op_jl_subb] = CC_O | CC_S,
3215
    [INDEX_op_jl_subw] = CC_O | CC_S,
3216
    [INDEX_op_jl_subl] = CC_O | CC_S,
3217

    
3218
    [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3219
    [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3220
    [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3221

    
3222
    [INDEX_op_loopnzw] = CC_Z,
3223
    [INDEX_op_loopnzl] = CC_Z,
3224
    [INDEX_op_loopzw] = CC_Z,
3225
    [INDEX_op_loopzl] = CC_Z,
3226

    
3227
    [INDEX_op_seto_T0_cc] = CC_O,
3228
    [INDEX_op_setb_T0_cc] = CC_C,
3229
    [INDEX_op_setz_T0_cc] = CC_Z,
3230
    [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3231
    [INDEX_op_sets_T0_cc] = CC_S,
3232
    [INDEX_op_setp_T0_cc] = CC_P,
3233
    [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3234
    [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3235

    
3236
    [INDEX_op_setb_T0_subb] = CC_C,
3237
    [INDEX_op_setb_T0_subw] = CC_C,
3238
    [INDEX_op_setb_T0_subl] = CC_C,
3239

    
3240
    [INDEX_op_setz_T0_subb] = CC_Z,
3241
    [INDEX_op_setz_T0_subw] = CC_Z,
3242
    [INDEX_op_setz_T0_subl] = CC_Z,
3243

    
3244
    [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3245
    [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3246
    [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3247

    
3248
    [INDEX_op_sets_T0_subb] = CC_S,
3249
    [INDEX_op_sets_T0_subw] = CC_S,
3250
    [INDEX_op_sets_T0_subl] = CC_S,
3251

    
3252
    [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3253
    [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3254
    [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3255

    
3256
    [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3257
    [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3258
    [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3259

    
3260
    [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3261
    [INDEX_op_cmc] = CC_C,
3262
    [INDEX_op_salc] = CC_C,
3263

    
3264
    [INDEX_op_rclb_T0_T1_cc] = CC_C,
3265
    [INDEX_op_rclw_T0_T1_cc] = CC_C,
3266
    [INDEX_op_rcll_T0_T1_cc] = CC_C,
3267
    [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3268
    [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3269
    [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3270
};
3271

    
3272
/* flags written by an operation */
3273
static uint16_t opc_write_flags[NB_OPS] = { 
3274
    [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3275
    [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3276
    [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3277
    [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3278
    [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3279
    [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3280
    [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3281
    [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3282
    [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3283
    [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3284
    [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3285
    [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3286
    [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3287
    [INDEX_op_incl_T0_cc] = CC_OSZAP,
3288
    [INDEX_op_decl_T0_cc] = CC_OSZAP,
3289
    [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3290

    
3291
    [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3292
    [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3293
    [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3294
    [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3295
    [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3296
    [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3297
    [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3298
    [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3299
    
3300
    /* bcd */
3301
    [INDEX_op_aam] = CC_OSZAPC,
3302
    [INDEX_op_aad] = CC_OSZAPC,
3303
    [INDEX_op_aas] = CC_OSZAPC,
3304
    [INDEX_op_aaa] = CC_OSZAPC,
3305
    [INDEX_op_das] = CC_OSZAPC,
3306
    [INDEX_op_daa] = CC_OSZAPC,
3307

    
3308
    [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3309
    [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3310
    [INDEX_op_clc] = CC_C,
3311
    [INDEX_op_stc] = CC_C,
3312
    [INDEX_op_cmc] = CC_C,
3313

    
3314
    [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3315
    [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3316
    [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3317
    [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3318
    [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3319
    [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3320

    
3321
    [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3322
    [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3323
    [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3324
    [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3325
    [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3326
    [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3327

    
3328
    [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3329
    [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3330
    [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3331

    
3332
    [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3333
    [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3334
    [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3335

    
3336
    [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3337
    [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3338
    [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3339

    
3340
    [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3341
    [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3342
    [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3343
    [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3344

    
3345
    [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3346
    [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3347
    [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3348
    [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3349

    
3350
    [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3351
    [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3352
    [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3353
    [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3354
    [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3355
    [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3356
    [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3357
    [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3358

    
3359
    [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3360
    [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3361
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3362
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3363

    
3364
    [INDEX_op_scasb] = CC_OSZAPC,
3365
    [INDEX_op_scasw] = CC_OSZAPC,
3366
    [INDEX_op_scasl] = CC_OSZAPC,
3367
    [INDEX_op_repz_scasb] = CC_OSZAPC,
3368
    [INDEX_op_repz_scasw] = CC_OSZAPC,
3369
    [INDEX_op_repz_scasl] = CC_OSZAPC,
3370
    [INDEX_op_repnz_scasb] = CC_OSZAPC,
3371
    [INDEX_op_repnz_scasw] = CC_OSZAPC,
3372
    [INDEX_op_repnz_scasl] = CC_OSZAPC,
3373

    
3374
    [INDEX_op_cmpsb] = CC_OSZAPC,
3375
    [INDEX_op_cmpsw] = CC_OSZAPC,
3376
    [INDEX_op_cmpsl] = CC_OSZAPC,
3377
    [INDEX_op_repz_cmpsb] = CC_OSZAPC,
3378
    [INDEX_op_repz_cmpsw] = CC_OSZAPC,
3379
    [INDEX_op_repz_cmpsl] = CC_OSZAPC,
3380
    [INDEX_op_repnz_cmpsb] = CC_OSZAPC,
3381
    [INDEX_op_repnz_cmpsw] = CC_OSZAPC,
3382
    [INDEX_op_repnz_cmpsl] = CC_OSZAPC,
3383

    
3384
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3385
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3386
};
3387

    
3388
/* simpler form of an operation if no flags need to be generated */
3389
static uint16_t opc_simpler[NB_OPS] = { 
3390
    [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3391
    [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3392
    [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3393
    [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3394
    [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3395
    [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3396
    [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3397
    [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3398

    
3399
    [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3400
    [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3401
    [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3402

    
3403
    [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3404
    [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3405
    [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3406

    
3407
    [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3408
    [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3409
    [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3410

    
3411
    [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3412
    [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3413
    [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3414

    
3415
    [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3416
    [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3417
    [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3418
};
3419

    
3420
static void optimize_flags_init(void)
3421
{
3422
    int i;
3423
    /* put default values in arrays */
3424
    for(i = 0; i < NB_OPS; i++) {
3425
        if (opc_simpler[i] == 0)
3426
            opc_simpler[i] = i;
3427
    }
3428
}
3429

    
3430
/* CPU flags computation optimization: we move backward thru the
3431
   generated code to see which flags are needed. The operation is
3432
   modified if suitable */
3433
static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3434
{
3435
    uint16_t *opc_ptr;
3436
    int live_flags, write_flags, op;
3437

    
3438
    opc_ptr = opc_buf + opc_buf_len;
3439
    /* live_flags contains the flags needed by the next instructions
3440
       in the code. At the end of the bloc, we consider that all the
3441
       flags are live. */
3442
    live_flags = CC_OSZAPC;
3443
    while (opc_ptr > opc_buf) {
3444
        op = *--opc_ptr;
3445
        /* if none of the flags written by the instruction is used,
3446
           then we can try to find a simpler instruction */
3447
        write_flags = opc_write_flags[op];
3448
        if ((live_flags & write_flags) == 0) {
3449
            *opc_ptr = opc_simpler[op];
3450
        }
3451
        /* compute the live flags before the instruction */
3452
        live_flags &= ~write_flags;
3453
        live_flags |= opc_read_flags[op];
3454
    }
3455
}
3456

    
3457

    
3458
#ifdef DEBUG_DISAS
3459
static const char *op_str[] = {
3460
#define DEF(s) #s,
3461
#include "opc-i386.h"
3462
#undef DEF
3463
};
3464

    
3465
static void dump_ops(const uint16_t *opc_buf)
3466
{
3467
    const uint16_t *opc_ptr;
3468
    int c;
3469
    opc_ptr = opc_buf;
3470
    for(;;) {
3471
        c = *opc_ptr++;
3472
        fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]);
3473
        if (c == INDEX_op_end)
3474
            break;
3475
    }
3476
}
3477

    
3478
#endif
3479

    
3480
/* XXX: make this buffer thread safe */
3481
/* XXX: make safe guess about sizes */
3482
#define MAX_OP_PER_INSTR 32
3483
#define OPC_BUF_SIZE 512
3484
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3485

    
3486
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3487

    
3488
static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3489
static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3490

    
3491
/* return non zero if the very first instruction is invalid so that
3492
   the virtual CPU can trigger an exception. */
3493
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
3494
                     int *gen_code_size_ptr,
3495
                     uint8_t *pc_start,  uint8_t *cs_base, int flags)
3496
{
3497
    DisasContext dc1, *dc = &dc1;
3498
    uint8_t *pc_ptr;
3499
    uint16_t *gen_opc_end;
3500
    int gen_code_size;
3501
    long ret;
3502
#ifdef DEBUG_DISAS
3503
    struct disassemble_info disasm_info;
3504
#endif
3505
    
3506
    /* generate intermediate code */
3507

    
3508
    dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3509
    dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3510
    dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3511
    dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3512
    dc->cc_op = CC_OP_DYNAMIC;
3513
    dc->cs_base = cs_base;
3514

    
3515
    gen_opc_ptr = gen_opc_buf;
3516
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3517
    gen_opparam_ptr = gen_opparam_buf;
3518

    
3519
    dc->is_jmp = 0;
3520
    pc_ptr = pc_start;
3521
    do {
3522
        ret = disas_insn(dc, pc_ptr);
3523
        if (ret == -1) {
3524
            /* we trigger an illegal instruction operation only if it
3525
               is the first instruction. Otherwise, we simply stop
3526
               generating the code just before it */
3527
            if (pc_ptr == pc_start)
3528
                return -1;
3529
            else
3530
                break;
3531
        }
3532
        pc_ptr = (void *)ret;
3533
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3534
    /* we must store the eflags state if it is not already done */
3535
    if (dc->cc_op != CC_OP_DYNAMIC)
3536
        gen_op_set_cc_op(dc->cc_op);
3537
    if (dc->is_jmp != 1) {
3538
        /* we add an additionnal jmp to update the simulated PC */
3539
        gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3540
    }
3541
    *gen_opc_ptr = INDEX_op_end;
3542

    
3543
    /* optimize flag computations */
3544
#ifdef DEBUG_DISAS
3545
    if (loglevel) {
3546
        uint8_t *pc;
3547
        int count;
3548

    
3549
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3550
#if 0        
3551
        disasm_info.flavour = bfd_get_flavour (abfd);
3552
        disasm_info.arch = bfd_get_arch (abfd);
3553
        disasm_info.mach = bfd_get_mach (abfd);
3554
#endif
3555
        disasm_info.endian = BFD_ENDIAN_LITTLE;
3556
        if (dc->code32)
3557
            disasm_info.mach = bfd_mach_i386_i386;
3558
        else
3559
            disasm_info.mach = bfd_mach_i386_i8086;
3560
        fprintf(logfile, "----------------\n");
3561
        fprintf(logfile, "IN:\n");
3562
        disasm_info.buffer = pc_start;
3563
        disasm_info.buffer_vma = (unsigned long)pc_start;
3564
        disasm_info.buffer_length = pc_ptr - pc_start;
3565
        pc = pc_start;
3566
        while (pc < pc_ptr) {
3567
            fprintf(logfile, "0x%08lx:  ", (long)pc);
3568
            count = print_insn_i386((unsigned long)pc, &disasm_info);
3569
            fprintf(logfile, "\n");
3570
            pc += count;
3571
        }
3572
        fprintf(logfile, "\n");
3573
        
3574
        fprintf(logfile, "OP:\n");
3575
        dump_ops(gen_opc_buf);
3576
        fprintf(logfile, "\n");
3577
    }
3578
#endif
3579

    
3580
    /* optimize flag computations */
3581
    optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3582

    
3583
#ifdef DEBUG_DISAS
3584
    if (loglevel) {
3585
        fprintf(logfile, "AFTER FLAGS OPT:\n");
3586
        dump_ops(gen_opc_buf);
3587
        fprintf(logfile, "\n");
3588
    }
3589
#endif
3590

    
3591
    /* generate machine code */
3592
    gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3593
    flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3594
    *gen_code_size_ptr = gen_code_size;
3595

    
3596
#ifdef DEBUG_DISAS
3597
    if (loglevel) {
3598
        uint8_t *pc;
3599
        int count;
3600

    
3601
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3602
#if 0        
3603
        disasm_info.flavour = bfd_get_flavour (abfd);
3604
        disasm_info.arch = bfd_get_arch (abfd);
3605
        disasm_info.mach = bfd_get_mach (abfd);
3606
#endif
3607
#ifdef WORDS_BIGENDIAN
3608
        disasm_info.endian = BFD_ENDIAN_BIG;
3609
#else
3610
        disasm_info.endian = BFD_ENDIAN_LITTLE;
3611
#endif        
3612
        disasm_info.mach = bfd_mach_i386_i386;
3613

    
3614
        pc = gen_code_buf;
3615
        disasm_info.buffer = pc;
3616
        disasm_info.buffer_vma = (unsigned long)pc;
3617
        disasm_info.buffer_length = *gen_code_size_ptr;
3618
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3619
        while (pc < gen_code_buf + *gen_code_size_ptr) {
3620
            fprintf(logfile, "0x%08lx:  ", (long)pc);
3621
            count = print_insn_i386((unsigned long)pc, &disasm_info);
3622
            fprintf(logfile, "\n");
3623
            pc += count;
3624
        }
3625
        fprintf(logfile, "\n");
3626
        fflush(logfile);
3627
    }
3628
#endif
3629
    return 0;
3630
}
3631

    
3632
CPUX86State *cpu_x86_init(void)
3633
{
3634
    CPUX86State *env;
3635
    int i;
3636
    static int inited;
3637

    
3638
    cpu_x86_tblocks_init();
3639

    
3640
    env = malloc(sizeof(CPUX86State));
3641
    if (!env)
3642
        return NULL;
3643
    memset(env, 0, sizeof(CPUX86State));
3644
    /* basic FPU init */
3645
    for(i = 0;i < 8; i++)
3646
        env->fptags[i] = 1;
3647
    env->fpuc = 0x37f;
3648
    /* flags setup */
3649
    env->eflags = 0;
3650

    
3651
    /* init various static tables */
3652
    if (!inited) {
3653
        inited = 1;
3654
        optimize_flags_init();
3655
    }
3656
    return env;
3657
}
3658

    
3659
void cpu_x86_close(CPUX86State *env)
3660
{
3661
    free(env);
3662
}