Statistics
| Branch: | Revision:

root / translate-i386.c @ 7d13299d

History | View | Annotate | Download (67.7 kB)

1
/*
2
 *  i386 translation
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program 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
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <assert.h>
26

    
27
#define DEBUG_DISAS
28

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

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

    
37
static uint8_t *gen_code_ptr;
38
int __op_param1, __op_param2, __op_param3;
39

    
40
extern FILE *logfile;
41
extern int loglevel;
42

    
43
/* supress that */
44
static void error(const char *fmt, ...)
45
{
46
    va_list ap;
47

    
48
    va_start(ap, fmt);
49
    fprintf(stderr, "\n");
50
    vfprintf(stderr, fmt, ap);
51
    fprintf(stderr, "\n");
52
    va_end(ap);
53
    exit(1);
54
}
55

    
56
#define PREFIX_REPZ 1
57
#define PREFIX_REPNZ 2
58
#define PREFIX_LOCK 4
59
#define PREFIX_CS 8
60
#define PREFIX_SS 0x10
61
#define PREFIX_DS 0x20
62
#define PREFIX_ES 0x40
63
#define PREFIX_FS 0x80
64
#define PREFIX_GS 0x100
65
#define PREFIX_DATA 0x200
66
#define PREFIX_ADR 0x400
67
#define PREFIX_FWAIT 0x800
68

    
69
typedef struct DisasContext {
70
    /* current insn context */
71
    int prefix;
72
    int aflag, dflag;
73
    uint8_t *pc; /* current pc */
74
    int cc_op; /* current CC operation */
75
    int f_st;
76
} DisasContext;
77

    
78
/* i386 arith/logic operations */
79
enum {
80
    OP_ADDL, 
81
    OP_ORL, 
82
    OP_ADCL, 
83
    OP_SBBL,
84
    OP_ANDL, 
85
    OP_SUBL, 
86
    OP_XORL, 
87
    OP_CMPL,
88
};
89

    
90
/* i386 shift ops */
91
enum {
92
    OP_ROL, 
93
    OP_ROR, 
94
    OP_RCL, 
95
    OP_RCR, 
96
    OP_SHL, 
97
    OP_SHR, 
98
    OP_SHL1, /* undocumented */
99
    OP_SAR = 7,
100
};
101

    
102
#include "op-i386.h"
103

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

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

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

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

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

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

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

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

    
346
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
347
    gen_op_addl_T0_T1_cc,
348
    gen_op_orl_T0_T1_cc,
349
    NULL,
350
    NULL,
351
    gen_op_andl_T0_T1_cc,
352
    gen_op_subl_T0_T1_cc,
353
    gen_op_xorl_T0_T1_cc,
354
    gen_op_cmpl_T0_T1_cc,
355
};
356

    
357
static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
358
    [OT_BYTE] = {
359
        gen_op_adcb_T0_T1_cc,
360
        gen_op_sbbb_T0_T1_cc,
361
    },
362
    [OT_WORD] = {
363
        gen_op_adcw_T0_T1_cc,
364
        gen_op_sbbw_T0_T1_cc,
365
    },
366
    [OT_LONG] = {
367
        gen_op_adcl_T0_T1_cc,
368
        gen_op_sbbl_T0_T1_cc,
369
    },
370
};
371

    
372
static const int cc_op_arithb[8] = {
373
    CC_OP_ADDB,
374
    CC_OP_LOGICB,
375
    CC_OP_ADDB,
376
    CC_OP_SUBB,
377
    CC_OP_LOGICB,
378
    CC_OP_SUBB,
379
    CC_OP_LOGICB,
380
    CC_OP_SUBB,
381
};
382

    
383
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
384
    [OT_BYTE] = {
385
        gen_op_rolb_T0_T1_cc,
386
        gen_op_rorb_T0_T1_cc,
387
        gen_op_rclb_T0_T1_cc,
388
        gen_op_rcrb_T0_T1_cc,
389
        gen_op_shlb_T0_T1_cc,
390
        gen_op_shrb_T0_T1_cc,
391
        gen_op_shlb_T0_T1_cc,
392
        gen_op_sarb_T0_T1_cc,
393
    },
394
    [OT_WORD] = {
395
        gen_op_rolw_T0_T1_cc,
396
        gen_op_rorw_T0_T1_cc,
397
        gen_op_rclw_T0_T1_cc,
398
        gen_op_rcrw_T0_T1_cc,
399
        gen_op_shlw_T0_T1_cc,
400
        gen_op_shrw_T0_T1_cc,
401
        gen_op_shlw_T0_T1_cc,
402
        gen_op_sarw_T0_T1_cc,
403
    },
404
    [OT_LONG] = {
405
        gen_op_roll_T0_T1_cc,
406
        gen_op_rorl_T0_T1_cc,
407
        gen_op_rcll_T0_T1_cc,
408
        gen_op_rcrl_T0_T1_cc,
409
        gen_op_shll_T0_T1_cc,
410
        gen_op_shrl_T0_T1_cc,
411
        gen_op_shll_T0_T1_cc,
412
        gen_op_sarl_T0_T1_cc,
413
    },
414
};
415

    
416
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
417
    [0] = {
418
        gen_op_shldw_T0_T1_im_cc,
419
        gen_op_shrdw_T0_T1_im_cc,
420
    },
421
    [1] = {
422
        gen_op_shldl_T0_T1_im_cc,
423
        gen_op_shrdl_T0_T1_im_cc,
424
    },
425
};
426

    
427
static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
428
    [0] = {
429
        gen_op_shldw_T0_T1_ECX_cc,
430
        gen_op_shrdw_T0_T1_ECX_cc,
431
    },
432
    [1] = {
433
        gen_op_shldl_T0_T1_ECX_cc,
434
        gen_op_shrdl_T0_T1_ECX_cc,
435
    },
436
};
437

    
438
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
439
    [0] = {
440
        gen_op_btw_T0_T1_cc,
441
        gen_op_btsw_T0_T1_cc,
442
        gen_op_btrw_T0_T1_cc,
443
        gen_op_btcw_T0_T1_cc,
444
    },
445
    [1] = {
446
        gen_op_btl_T0_T1_cc,
447
        gen_op_btsl_T0_T1_cc,
448
        gen_op_btrl_T0_T1_cc,
449
        gen_op_btcl_T0_T1_cc,
450
    },
451
};
452

    
453
static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
454
    [0] = {
455
        gen_op_bsfw_T0_cc,
456
        gen_op_bsrw_T0_cc,
457
    },
458
    [1] = {
459
        gen_op_bsfl_T0_cc,
460
        gen_op_bsrl_T0_cc,
461
    },
462
};
463

    
464
static GenOpFunc *gen_op_lds_T0_A0[3] = {
465
    gen_op_ldsb_T0_A0,
466
    gen_op_ldsw_T0_A0,
467
};
468

    
469
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
470
    gen_op_ldub_T0_A0,
471
    gen_op_lduw_T0_A0,
472
};
473

    
474
/* sign does not matter */
475
static GenOpFunc *gen_op_ld_T0_A0[3] = {
476
    gen_op_ldub_T0_A0,
477
    gen_op_lduw_T0_A0,
478
    gen_op_ldl_T0_A0,
479
};
480

    
481
static GenOpFunc *gen_op_ld_T1_A0[3] = {
482
    gen_op_ldub_T1_A0,
483
    gen_op_lduw_T1_A0,
484
    gen_op_ldl_T1_A0,
485
};
486

    
487
static GenOpFunc *gen_op_st_T0_A0[3] = {
488
    gen_op_stb_T0_A0,
489
    gen_op_stw_T0_A0,
490
    gen_op_stl_T0_A0,
491
};
492

    
493
static GenOpFunc *gen_op_movs[6] = {
494
    gen_op_movsb,
495
    gen_op_movsw,
496
    gen_op_movsl,
497
    gen_op_rep_movsb,
498
    gen_op_rep_movsw,
499
    gen_op_rep_movsl,
500
};
501

    
502
static GenOpFunc *gen_op_stos[6] = {
503
    gen_op_stosb,
504
    gen_op_stosw,
505
    gen_op_stosl,
506
    gen_op_rep_stosb,
507
    gen_op_rep_stosw,
508
    gen_op_rep_stosl,
509
};
510

    
511
static GenOpFunc *gen_op_lods[6] = {
512
    gen_op_lodsb,
513
    gen_op_lodsw,
514
    gen_op_lodsl,
515
    gen_op_rep_lodsb,
516
    gen_op_rep_lodsw,
517
    gen_op_rep_lodsl,
518
};
519

    
520
static GenOpFunc *gen_op_scas[9] = {
521
    gen_op_scasb,
522
    gen_op_scasw,
523
    gen_op_scasl,
524
    gen_op_repz_scasb,
525
    gen_op_repz_scasw,
526
    gen_op_repz_scasl,
527
    gen_op_repnz_scasb,
528
    gen_op_repnz_scasw,
529
    gen_op_repnz_scasl,
530
};
531

    
532
static GenOpFunc *gen_op_cmps[9] = {
533
    gen_op_cmpsb,
534
    gen_op_cmpsw,
535
    gen_op_cmpsl,
536
    gen_op_repz_cmpsb,
537
    gen_op_repz_cmpsw,
538
    gen_op_repz_cmpsl,
539
    gen_op_repnz_cmpsb,
540
    gen_op_repnz_cmpsw,
541
    gen_op_repnz_cmpsl,
542
};
543

    
544
static GenOpFunc *gen_op_ins[6] = {
545
    gen_op_insb,
546
    gen_op_insw,
547
    gen_op_insl,
548
    gen_op_rep_insb,
549
    gen_op_rep_insw,
550
    gen_op_rep_insl,
551
};
552

    
553

    
554
static GenOpFunc *gen_op_outs[6] = {
555
    gen_op_outsb,
556
    gen_op_outsw,
557
    gen_op_outsl,
558
    gen_op_rep_outsb,
559
    gen_op_rep_outsw,
560
    gen_op_rep_outsl,
561
};
562

    
563
static GenOpFunc *gen_op_in[3] = {
564
    gen_op_inb_T0_T1,
565
    gen_op_inw_T0_T1,
566
    gen_op_inl_T0_T1,
567
};
568

    
569
static GenOpFunc *gen_op_out[3] = {
570
    gen_op_outb_T0_T1,
571
    gen_op_outw_T0_T1,
572
    gen_op_outl_T0_T1,
573
};
574

    
575
enum {
576
    JCC_O,
577
    JCC_B,
578
    JCC_Z,
579
    JCC_BE,
580
    JCC_S,
581
    JCC_P,
582
    JCC_L,
583
    JCC_LE,
584
};
585

    
586
static GenOpFunc2 *gen_jcc_slow[8] = {
587
    gen_op_jo_cc,
588
    gen_op_jb_cc,
589
    gen_op_jz_cc,
590
    gen_op_jbe_cc,
591
    gen_op_js_cc,
592
    gen_op_jp_cc,
593
    gen_op_jl_cc,
594
    gen_op_jle_cc,
595
};
596
    
597
static GenOpFunc2 *gen_jcc_sub[3][8] = {
598
    [OT_BYTE] = {
599
        NULL,
600
        gen_op_jb_subb,
601
        gen_op_jz_subb,
602
        gen_op_jbe_subb,
603
        gen_op_js_subb,
604
        NULL,
605
        gen_op_jl_subb,
606
        gen_op_jle_subb,
607
    },
608
    [OT_WORD] = {
609
        NULL,
610
        gen_op_jb_subw,
611
        gen_op_jz_subw,
612
        gen_op_jbe_subw,
613
        gen_op_js_subw,
614
        NULL,
615
        gen_op_jl_subw,
616
        gen_op_jle_subw,
617
    },
618
    [OT_LONG] = {
619
        NULL,
620
        gen_op_jb_subl,
621
        gen_op_jz_subl,
622
        gen_op_jbe_subl,
623
        gen_op_js_subl,
624
        NULL,
625
        gen_op_jl_subl,
626
        gen_op_jle_subl,
627
    },
628
};
629

    
630
static GenOpFunc *gen_setcc_slow[8] = {
631
    gen_op_seto_T0_cc,
632
    gen_op_setb_T0_cc,
633
    gen_op_setz_T0_cc,
634
    gen_op_setbe_T0_cc,
635
    gen_op_sets_T0_cc,
636
    gen_op_setp_T0_cc,
637
    gen_op_setl_T0_cc,
638
    gen_op_setle_T0_cc,
639
};
640

    
641
static GenOpFunc *gen_setcc_sub[3][8] = {
642
    [OT_BYTE] = {
643
        NULL,
644
        gen_op_setb_T0_subb,
645
        gen_op_setz_T0_subb,
646
        gen_op_setbe_T0_subb,
647
        gen_op_sets_T0_subb,
648
        NULL,
649
        gen_op_setl_T0_subb,
650
        gen_op_setle_T0_subb,
651
    },
652
    [OT_WORD] = {
653
        NULL,
654
        gen_op_setb_T0_subw,
655
        gen_op_setz_T0_subw,
656
        gen_op_setbe_T0_subw,
657
        gen_op_sets_T0_subw,
658
        NULL,
659
        gen_op_setl_T0_subw,
660
        gen_op_setle_T0_subw,
661
    },
662
    [OT_LONG] = {
663
        NULL,
664
        gen_op_setb_T0_subl,
665
        gen_op_setz_T0_subl,
666
        gen_op_setbe_T0_subl,
667
        gen_op_sets_T0_subl,
668
        NULL,
669
        gen_op_setl_T0_subl,
670
        gen_op_setle_T0_subl,
671
    },
672
};
673

    
674
static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
675
    gen_op_fadd_ST0_FT0,
676
    gen_op_fmul_ST0_FT0,
677
    gen_op_fcom_ST0_FT0,
678
    gen_op_fcom_ST0_FT0,
679
    gen_op_fsub_ST0_FT0,
680
    gen_op_fsubr_ST0_FT0,
681
    gen_op_fdiv_ST0_FT0,
682
    gen_op_fdivr_ST0_FT0,
683
};
684

    
685
/* NOTE the exception in "r" op ordering */
686
static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
687
    gen_op_fadd_STN_ST0,
688
    gen_op_fmul_STN_ST0,
689
    NULL,
690
    NULL,
691
    gen_op_fsubr_STN_ST0,
692
    gen_op_fsub_STN_ST0,
693
    gen_op_fdivr_STN_ST0,
694
    gen_op_fdiv_STN_ST0,
695
};
696

    
697
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
698
{
699
    if (d != OR_TMP0)
700
        gen_op_mov_TN_reg[ot][0][d]();
701
    if (s != OR_TMP1)
702
        gen_op_mov_TN_reg[ot][1][s]();
703
    if (op == OP_ADCL || op == OP_SBBL) {
704
        if (s1->cc_op != CC_OP_DYNAMIC)
705
            gen_op_set_cc_op(s1->cc_op);
706
        gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
707
        s1->cc_op = CC_OP_DYNAMIC;
708
    } else {
709
        gen_op_arith_T0_T1_cc[op]();
710
        s1->cc_op = cc_op_arithb[op] + ot;
711
    }
712
    if (d != OR_TMP0 && op != OP_CMPL)
713
        gen_op_mov_reg_T0[ot][d]();
714
}
715

    
716
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
717
{
718
    gen_op_movl_T1_im(c);
719
    gen_op(s1, op, ot, d, OR_TMP1);
720
}
721

    
722
static void gen_inc(DisasContext *s1, int ot, int d, int c)
723
{
724
    if (d != OR_TMP0)
725
        gen_op_mov_TN_reg[ot][0][d]();
726
    if (s1->cc_op != CC_OP_DYNAMIC)
727
        gen_op_set_cc_op(s1->cc_op);
728
    if (c > 0) {
729
        gen_op_incl_T0_cc();
730
        s1->cc_op = CC_OP_INCB + ot;
731
    } else {
732
        gen_op_decl_T0_cc();
733
        s1->cc_op = CC_OP_DECB + ot;
734
    }
735
    if (d != OR_TMP0)
736
        gen_op_mov_reg_T0[ot][d]();
737
}
738

    
739
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
740
{
741
    if (d != OR_TMP0)
742
        gen_op_mov_TN_reg[ot][0][d]();
743
    if (s != OR_TMP1)
744
        gen_op_mov_TN_reg[ot][1][s]();
745
    /* for zero counts, flags are not updated, so must do it dynamically */
746
    if (s1->cc_op != CC_OP_DYNAMIC)
747
        gen_op_set_cc_op(s1->cc_op);
748

    
749
    gen_op_shift_T0_T1_cc[ot][op]();
750

    
751
    if (d != OR_TMP0)
752
        gen_op_mov_reg_T0[ot][d]();
753
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
754
}
755

    
756
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
757
{
758
    /* currently not optimized */
759
    gen_op_movl_T1_im(c);
760
    gen_shift(s1, op, ot, d, OR_TMP1);
761
}
762

    
763
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
764
{
765
    int havesib;
766
    int havebase;
767
    int base, disp;
768
    int index = 0;
769
    int scale = 0;
770
    int reg1, reg2, opreg;
771
    int mod, rm, code;
772

    
773
    mod = (modrm >> 6) & 3;
774
    rm = modrm & 7;
775

    
776
    if (s->aflag) {
777

    
778
        havesib = 0;
779
        havebase = 1;
780
        base = rm;
781
        
782
        if (base == 4) {
783
            havesib = 1;
784
            code = ldub(s->pc++);
785
            scale = (code >> 6) & 3;
786
            index = (code >> 3) & 7;
787
            base = code & 7;
788
        }
789

    
790
        switch (mod) {
791
        case 0:
792
            if (base == 5) {
793
                havebase = 0;
794
                disp = ldl(s->pc);
795
                s->pc += 4;
796
            } else {
797
                disp = 0;
798
            }
799
            break;
800
        case 1:
801
            disp = (int8_t)ldub(s->pc++);
802
            break;
803
        default:
804
        case 2:
805
            disp = ldl(s->pc);
806
            s->pc += 4;
807
            break;
808
        }
809

    
810
        reg1 = OR_ZERO;
811
        reg2 = OR_ZERO;
812
          
813
        if (havebase || (havesib && (index != 4 || scale != 0))) {
814
            if (havebase)
815
                reg1 = OR_EAX + base;
816
            if (havesib && index != 4) {
817
                if (havebase)
818
                    reg2 = index + OR_EAX;
819
                else
820
                    reg1 = index + OR_EAX;
821
            }
822
        }
823
        /* XXX: disp only ? */
824
        if (reg2 == OR_ZERO) {
825
            /* op: disp + (reg1 << scale) */
826
            if (reg1 == OR_ZERO) {
827
                gen_op_movl_A0_im(disp);
828
            } else if (scale == 0 && disp == 0) {
829
                gen_op_movl_A0_reg[reg1]();
830
            } else {
831
                gen_op_movl_A0_im(disp);
832
                gen_op_addl_A0_reg_sN[scale][reg1]();
833
            }
834
        } else {
835
            /* op: disp + reg1 + (reg2 << scale) */
836
            if (disp != 0) {
837
                gen_op_movl_A0_im(disp);
838
                gen_op_addl_A0_reg_sN[0][reg1]();
839
            } else {
840
                gen_op_movl_A0_reg[reg1]();
841
            }
842
            gen_op_addl_A0_reg_sN[scale][reg2]();
843
        }
844
    } else {
845
        switch (mod) {
846
        case 0:
847
            if (rm == 6) {
848
                disp = lduw(s->pc);
849
                s->pc += 2;
850
                gen_op_movl_A0_im(disp);
851
                goto no_rm;
852
            } else {
853
                disp = 0;
854
            }
855
            break;
856
        case 1:
857
            disp = (int8_t)ldub(s->pc++);
858
            break;
859
        default:
860
        case 2:
861
            disp = lduw(s->pc);
862
            s->pc += 2;
863
            break;
864
        }
865
        switch(rm) {
866
        case 0:
867
            gen_op_movl_A0_reg[R_EBX]();
868
            gen_op_addl_A0_reg_sN[0][R_ESI]();
869
            break;
870
        case 1:
871
            gen_op_movl_A0_reg[R_EBX]();
872
            gen_op_addl_A0_reg_sN[0][R_EDI]();
873
            break;
874
        case 2:
875
            gen_op_movl_A0_reg[R_EBP]();
876
            gen_op_addl_A0_reg_sN[0][R_ESI]();
877
            break;
878
        case 3:
879
            gen_op_movl_A0_reg[R_EBP]();
880
            gen_op_addl_A0_reg_sN[0][R_EDI]();
881
            break;
882
        case 4:
883
            gen_op_movl_A0_reg[R_ESI]();
884
            break;
885
        case 5:
886
            gen_op_movl_A0_reg[R_EDI]();
887
            break;
888
        case 6:
889
            gen_op_movl_A0_reg[R_EBP]();
890
            break;
891
        default:
892
        case 7:
893
            gen_op_movl_A0_reg[R_EBX]();
894
            break;
895
        }
896
        if (disp != 0)
897
            gen_op_addl_A0_im(disp);
898
        gen_op_andl_A0_ffff();
899
    no_rm: ;
900
    }
901
    opreg = OR_A0;
902
    disp = 0;
903
    *reg_ptr = opreg;
904
    *offset_ptr = disp;
905
}
906

    
907
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
908
   OR_TMP0 */
909
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
910
{
911
    int mod, rm, opreg, disp;
912

    
913
    mod = (modrm >> 6) & 3;
914
    rm = modrm & 7;
915
    if (mod == 3) {
916
        if (is_store) {
917
            if (reg != OR_TMP0)
918
                gen_op_mov_TN_reg[ot][0][reg]();
919
            gen_op_mov_reg_T0[ot][rm]();
920
        } else {
921
            gen_op_mov_TN_reg[ot][0][rm]();
922
            if (reg != OR_TMP0)
923
                gen_op_mov_reg_T0[ot][reg]();
924
        }
925
    } else {
926
        gen_lea_modrm(s, modrm, &opreg, &disp);
927
        if (is_store) {
928
            if (reg != OR_TMP0)
929
                gen_op_mov_TN_reg[ot][0][reg]();
930
            gen_op_st_T0_A0[ot]();
931
        } else {
932
            gen_op_ld_T0_A0[ot]();
933
            if (reg != OR_TMP0)
934
                gen_op_mov_reg_T0[ot][reg]();
935
        }
936
    }
937
}
938

    
939
static inline uint32_t insn_get(DisasContext *s, int ot)
940
{
941
    uint32_t ret;
942

    
943
    switch(ot) {
944
    case OT_BYTE:
945
        ret = ldub(s->pc);
946
        s->pc++;
947
        break;
948
    case OT_WORD:
949
        ret = lduw(s->pc);
950
        s->pc += 2;
951
        break;
952
    default:
953
    case OT_LONG:
954
        ret = ldl(s->pc);
955
        s->pc += 4;
956
        break;
957
    }
958
    return ret;
959
}
960

    
961
static void gen_jcc(DisasContext *s, int b, int val)
962
{
963
    int inv, jcc_op;
964
    GenOpFunc2 *func;
965

    
966
    inv = b & 1;
967
    jcc_op = (b >> 1) & 7;
968
    switch(s->cc_op) {
969
        /* we optimize the cmp/jcc case */
970
    case CC_OP_SUBB:
971
    case CC_OP_SUBW:
972
    case CC_OP_SUBL:
973
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
974
        if (!func)
975
            goto slow_jcc;
976
        break;
977
        
978
        /* some jumps are easy to compute */
979
    case CC_OP_ADDB:
980
    case CC_OP_ADDW:
981
    case CC_OP_ADDL:
982
    case CC_OP_ADCB:
983
    case CC_OP_ADCW:
984
    case CC_OP_ADCL:
985
    case CC_OP_SBBB:
986
    case CC_OP_SBBW:
987
    case CC_OP_SBBL:
988
    case CC_OP_LOGICB:
989
    case CC_OP_LOGICW:
990
    case CC_OP_LOGICL:
991
    case CC_OP_INCB:
992
    case CC_OP_INCW:
993
    case CC_OP_INCL:
994
    case CC_OP_DECB:
995
    case CC_OP_DECW:
996
    case CC_OP_DECL:
997
    case CC_OP_SHLB:
998
    case CC_OP_SHLW:
999
    case CC_OP_SHLL:
1000
    case CC_OP_SARB:
1001
    case CC_OP_SARW:
1002
    case CC_OP_SARL:
1003
        switch(jcc_op) {
1004
        case JCC_Z:
1005
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1006
            break;
1007
        case JCC_S:
1008
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1009
            break;
1010
        default:
1011
            goto slow_jcc;
1012
        }
1013
        break;
1014
    default:
1015
    slow_jcc:
1016
        if (s->cc_op != CC_OP_DYNAMIC)
1017
            gen_op_set_cc_op(s->cc_op);
1018
        func = gen_jcc_slow[jcc_op];
1019
        break;
1020
    }
1021
    if (!inv) {
1022
        func(val, (long)s->pc);
1023
    } else {
1024
        func((long)s->pc, val);
1025
    }
1026
}
1027

    
1028
static void gen_setcc(DisasContext *s, int b)
1029
{
1030
    int inv, jcc_op;
1031
    GenOpFunc *func;
1032

    
1033
    inv = b & 1;
1034
    jcc_op = (b >> 1) & 7;
1035
    switch(s->cc_op) {
1036
        /* we optimize the cmp/jcc case */
1037
    case CC_OP_SUBB:
1038
    case CC_OP_SUBW:
1039
    case CC_OP_SUBL:
1040
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1041
        if (!func)
1042
            goto slow_jcc;
1043
        break;
1044
        
1045
        /* some jumps are easy to compute */
1046
    case CC_OP_ADDB:
1047
    case CC_OP_ADDW:
1048
    case CC_OP_ADDL:
1049
    case CC_OP_LOGICB:
1050
    case CC_OP_LOGICW:
1051
    case CC_OP_LOGICL:
1052
    case CC_OP_INCB:
1053
    case CC_OP_INCW:
1054
    case CC_OP_INCL:
1055
    case CC_OP_DECB:
1056
    case CC_OP_DECW:
1057
    case CC_OP_DECL:
1058
    case CC_OP_SHLB:
1059
    case CC_OP_SHLW:
1060
    case CC_OP_SHLL:
1061
        switch(jcc_op) {
1062
        case JCC_Z:
1063
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1064
            break;
1065
        case JCC_S:
1066
            func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1067
            break;
1068
        default:
1069
            goto slow_jcc;
1070
        }
1071
        break;
1072
    default:
1073
    slow_jcc:
1074
        if (s->cc_op != CC_OP_DYNAMIC)
1075
            gen_op_set_cc_op(s->cc_op);
1076
        func = gen_setcc_slow[jcc_op];
1077
        break;
1078
    }
1079
    func();
1080
    if (inv) {
1081
        gen_op_xor_T0_1();
1082
    }
1083
}
1084

    
1085
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1086
   is set to true if the instruction sets the PC (last instruction of
1087
   a basic block) */
1088
long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1089
{
1090
    int b, prefixes, aflag, dflag;
1091
    int shift, ot;
1092
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1093

    
1094
    s->pc = pc_start;
1095
    prefixes = 0;
1096
    aflag = 1;
1097
    dflag = 1;
1098
    //    cur_pc = s->pc; /* for insn generation */
1099
 next_byte:
1100
    b = ldub(s->pc);
1101
    s->pc++;
1102
    /* check prefixes */
1103
    switch (b) {
1104
    case 0xf3:
1105
        prefixes |= PREFIX_REPZ;
1106
        goto next_byte;
1107
    case 0xf2:
1108
        prefixes |= PREFIX_REPNZ;
1109
        goto next_byte;
1110
    case 0xf0:
1111
        prefixes |= PREFIX_LOCK;
1112
        goto next_byte;
1113
    case 0x2e:
1114
        prefixes |= PREFIX_CS;
1115
        goto next_byte;
1116
    case 0x36:
1117
        prefixes |= PREFIX_SS;
1118
        goto next_byte;
1119
    case 0x3e:
1120
        prefixes |= PREFIX_DS;
1121
        goto next_byte;
1122
    case 0x26:
1123
        prefixes |= PREFIX_ES;
1124
        goto next_byte;
1125
    case 0x64:
1126
        prefixes |= PREFIX_FS;
1127
        goto next_byte;
1128
    case 0x65:
1129
        prefixes |= PREFIX_GS;
1130
        goto next_byte;
1131
    case 0x66:
1132
        prefixes |= PREFIX_DATA;
1133
        goto next_byte;
1134
    case 0x67:
1135
        prefixes |= PREFIX_ADR;
1136
        goto next_byte;
1137
    case 0x9b:
1138
        prefixes |= PREFIX_FWAIT;
1139
        goto next_byte;
1140
    }
1141

    
1142
    if (prefixes & PREFIX_DATA)
1143
        dflag ^= 1;
1144
    if (prefixes & PREFIX_ADR)
1145
        aflag ^= 1;
1146

    
1147
    s->prefix = prefixes;
1148
    s->aflag = aflag;
1149
    s->dflag = dflag;
1150

    
1151
    /* now check op code */
1152
 reswitch:
1153
    switch(b) {
1154
    case 0x0f:
1155
        /**************************/
1156
        /* extended op code */
1157
        b = ldub(s->pc++) | 0x100;
1158
        goto reswitch;
1159
        
1160
        /**************************/
1161
        /* arith & logic */
1162
    case 0x00 ... 0x05:
1163
    case 0x08 ... 0x0d:
1164
    case 0x10 ... 0x15:
1165
    case 0x18 ... 0x1d:
1166
    case 0x20 ... 0x25:
1167
    case 0x28 ... 0x2d:
1168
    case 0x30 ... 0x35:
1169
    case 0x38 ... 0x3d:
1170
        {
1171
            int op, f, val;
1172
            op = (b >> 3) & 7;
1173
            f = (b >> 1) & 3;
1174

    
1175
            if ((b & 1) == 0)
1176
                ot = OT_BYTE;
1177
            else
1178
                ot = dflag ? OT_LONG : OT_WORD;
1179
            
1180
            switch(f) {
1181
            case 0: /* OP Ev, Gv */
1182
                modrm = ldub(s->pc++);
1183
                reg = ((modrm >> 3) & 7) + OR_EAX;
1184
                mod = (modrm >> 6) & 3;
1185
                rm = modrm & 7;
1186
                if (mod != 3) {
1187
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1188
                    gen_op_ld_T0_A0[ot]();
1189
                    opreg = OR_TMP0;
1190
                } else {
1191
                    opreg = OR_EAX + rm;
1192
                }
1193
                gen_op(s, op, ot, opreg, reg);
1194
                if (mod != 3 && op != 7) {
1195
                    gen_op_st_T0_A0[ot]();
1196
                }
1197
                break;
1198
            case 1: /* OP Gv, Ev */
1199
                modrm = ldub(s->pc++);
1200
                mod = (modrm >> 6) & 3;
1201
                reg = ((modrm >> 3) & 7) + OR_EAX;
1202
                rm = modrm & 7;
1203
                if (mod != 3) {
1204
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1205
                    gen_op_ld_T1_A0[ot]();
1206
                    opreg = OR_TMP1;
1207
                } else {
1208
                    opreg = OR_EAX + rm;
1209
                }
1210
                gen_op(s, op, ot, reg, opreg);
1211
                break;
1212
            case 2: /* OP A, Iv */
1213
                val = insn_get(s, ot);
1214
                gen_opi(s, op, ot, OR_EAX, val);
1215
                break;
1216
            }
1217
        }
1218
        break;
1219

    
1220
    case 0x80: /* GRP1 */
1221
    case 0x81:
1222
    case 0x83:
1223
        {
1224
            int val;
1225

    
1226
            if ((b & 1) == 0)
1227
                ot = OT_BYTE;
1228
            else
1229
                ot = dflag ? OT_LONG : OT_WORD;
1230
            
1231
            modrm = ldub(s->pc++);
1232
            mod = (modrm >> 6) & 3;
1233
            rm = modrm & 7;
1234
            op = (modrm >> 3) & 7;
1235
            
1236
            if (mod != 3) {
1237
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1238
                gen_op_ld_T0_A0[ot]();
1239
                opreg = OR_TMP0;
1240
            } else {
1241
                opreg = rm + OR_EAX;
1242
            }
1243

    
1244
            switch(b) {
1245
            default:
1246
            case 0x80:
1247
            case 0x81:
1248
                val = insn_get(s, ot);
1249
                break;
1250
            case 0x83:
1251
                val = (int8_t)insn_get(s, OT_BYTE);
1252
                break;
1253
            }
1254

    
1255
            gen_opi(s, op, ot, opreg, val);
1256
            if (op != 7 && mod != 3) {
1257
                gen_op_st_T0_A0[ot]();
1258
            }
1259
        }
1260
        break;
1261

    
1262
        /**************************/
1263
        /* inc, dec, and other misc arith */
1264
    case 0x40 ... 0x47: /* inc Gv */
1265
        ot = dflag ? OT_LONG : OT_WORD;
1266
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1267
        break;
1268
    case 0x48 ... 0x4f: /* dec Gv */
1269
        ot = dflag ? OT_LONG : OT_WORD;
1270
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1271
        break;
1272
    case 0xf6: /* GRP3 */
1273
    case 0xf7:
1274
        if ((b & 1) == 0)
1275
            ot = OT_BYTE;
1276
        else
1277
            ot = dflag ? OT_LONG : OT_WORD;
1278

    
1279
        modrm = ldub(s->pc++);
1280
        mod = (modrm >> 6) & 3;
1281
        rm = modrm & 7;
1282
        op = (modrm >> 3) & 7;
1283
        if (mod != 3) {
1284
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1285
            gen_op_ld_T0_A0[ot]();
1286
        } else {
1287
            gen_op_mov_TN_reg[ot][0][rm]();
1288
        }
1289

    
1290
        switch(op) {
1291
        case 0: /* test */
1292
            val = insn_get(s, ot);
1293
            gen_op_movl_T1_im(val);
1294
            gen_op_testl_T0_T1_cc();
1295
            s->cc_op = CC_OP_LOGICB + ot;
1296
            break;
1297
        case 2: /* not */
1298
            gen_op_notl_T0();
1299
            if (mod != 3) {
1300
                gen_op_st_T0_A0[ot]();
1301
            } else {
1302
                gen_op_mov_reg_T0[ot][rm]();
1303
            }
1304
            break;
1305
        case 3: /* neg */
1306
            gen_op_negl_T0_cc();
1307
            if (mod != 3) {
1308
                gen_op_st_T0_A0[ot]();
1309
            } else {
1310
                gen_op_mov_reg_T0[ot][rm]();
1311
            }
1312
            s->cc_op = CC_OP_SUBB + ot;
1313
            break;
1314
        case 4: /* mul */
1315
            switch(ot) {
1316
            case OT_BYTE:
1317
                gen_op_mulb_AL_T0();
1318
                break;
1319
            case OT_WORD:
1320
                gen_op_mulw_AX_T0();
1321
                break;
1322
            default:
1323
            case OT_LONG:
1324
                gen_op_mull_EAX_T0();
1325
                break;
1326
            }
1327
            s->cc_op = CC_OP_MUL;
1328
            break;
1329
        case 5: /* imul */
1330
            switch(ot) {
1331
            case OT_BYTE:
1332
                gen_op_imulb_AL_T0();
1333
                break;
1334
            case OT_WORD:
1335
                gen_op_imulw_AX_T0();
1336
                break;
1337
            default:
1338
            case OT_LONG:
1339
                gen_op_imull_EAX_T0();
1340
                break;
1341
            }
1342
            s->cc_op = CC_OP_MUL;
1343
            break;
1344
        case 6: /* div */
1345
            switch(ot) {
1346
            case OT_BYTE:
1347
                gen_op_divb_AL_T0();
1348
                break;
1349
            case OT_WORD:
1350
                gen_op_divw_AX_T0();
1351
                break;
1352
            default:
1353
            case OT_LONG:
1354
                gen_op_divl_EAX_T0();
1355
                break;
1356
            }
1357
            break;
1358
        case 7: /* idiv */
1359
            switch(ot) {
1360
            case OT_BYTE:
1361
                gen_op_idivb_AL_T0();
1362
                break;
1363
            case OT_WORD:
1364
                gen_op_idivw_AX_T0();
1365
                break;
1366
            default:
1367
            case OT_LONG:
1368
                gen_op_idivl_EAX_T0();
1369
                break;
1370
            }
1371
            break;
1372
        default:
1373
            error("GRP3: bad instruction");
1374
            return -1;
1375
        }
1376
        break;
1377

    
1378
    case 0xfe: /* GRP4 */
1379
    case 0xff: /* GRP5 */
1380
        if ((b & 1) == 0)
1381
            ot = OT_BYTE;
1382
        else
1383
            ot = dflag ? OT_LONG : OT_WORD;
1384

    
1385
        modrm = ldub(s->pc++);
1386
        mod = (modrm >> 6) & 3;
1387
        rm = modrm & 7;
1388
        op = (modrm >> 3) & 7;
1389
        if (op >= 2 && b == 0xfe) {
1390
            error("GRP4: bad instruction");
1391
            return -1;
1392
        }
1393
        if (mod != 3) {
1394
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1395
            gen_op_ld_T0_A0[ot]();
1396
        } else {
1397
            gen_op_mov_TN_reg[ot][0][rm]();
1398
        }
1399

    
1400
        switch(op) {
1401
        case 0: /* inc Ev */
1402
            gen_inc(s, ot, OR_TMP0, 1);
1403
            if (mod != 3)
1404
                gen_op_st_T0_A0[ot]();
1405
            else
1406
                gen_op_mov_reg_T0[ot][rm]();
1407
            break;
1408
        case 1: /* dec Ev */
1409
            gen_inc(s, ot, OR_TMP0, -1);
1410
            if (mod != 3)
1411
                gen_op_st_T0_A0[ot]();
1412
            else
1413
                gen_op_mov_reg_T0[ot][rm]();
1414
            break;
1415
        case 2: /* call Ev */
1416
            gen_op_movl_T1_im((long)s->pc);
1417
            gen_op_pushl_T1();
1418
            gen_op_jmp_T0();
1419
            *is_jmp_ptr = 1;
1420
            break;
1421
        case 4: /* jmp Ev */
1422
            gen_op_jmp_T0();
1423
            *is_jmp_ptr = 1;
1424
            break;
1425
        case 6: /* push Ev */
1426
            gen_op_pushl_T0();
1427
            break;
1428
        default:
1429
            error("GRP5: bad instruction");
1430
            return -1;
1431
        }
1432
        break;
1433

    
1434
    case 0x84: /* test Ev, Gv */
1435
    case 0x85: 
1436
        if ((b & 1) == 0)
1437
            ot = OT_BYTE;
1438
        else
1439
            ot = dflag ? OT_LONG : OT_WORD;
1440

    
1441
        modrm = ldub(s->pc++);
1442
        mod = (modrm >> 6) & 3;
1443
        rm = modrm & 7;
1444
        reg = (modrm >> 3) & 7;
1445
        
1446
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1447
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1448
        gen_op_testl_T0_T1_cc();
1449
        s->cc_op = CC_OP_LOGICB + ot;
1450
        break;
1451
        
1452
    case 0xa8: /* test eAX, Iv */
1453
    case 0xa9:
1454
        if ((b & 1) == 0)
1455
            ot = OT_BYTE;
1456
        else
1457
            ot = dflag ? OT_LONG : OT_WORD;
1458
        val = insn_get(s, ot);
1459

    
1460
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1461
        gen_op_movl_T1_im(val);
1462
        gen_op_testl_T0_T1_cc();
1463
        s->cc_op = CC_OP_LOGICB + ot;
1464
        break;
1465
        
1466
    case 0x98: /* CWDE/CBW */
1467
        if (dflag)
1468
            gen_op_movswl_EAX_AX();
1469
        else
1470
            gen_op_movsbw_AX_AL();
1471
        break;
1472
    case 0x99: /* CDQ/CWD */
1473
        if (dflag)
1474
            gen_op_movslq_EDX_EAX();
1475
        else
1476
            gen_op_movswl_DX_AX();
1477
        break;
1478
    case 0x1af: /* imul Gv, Ev */
1479
    case 0x69: /* imul Gv, Ev, I */
1480
    case 0x6b:
1481
        ot = dflag ? OT_LONG : OT_WORD;
1482
        modrm = ldub(s->pc++);
1483
        reg = ((modrm >> 3) & 7) + OR_EAX;
1484
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1485
        if (b == 0x69) {
1486
            val = insn_get(s, ot);
1487
            gen_op_movl_T1_im(val);
1488
        } else if (b == 0x6b) {
1489
            val = insn_get(s, OT_BYTE);
1490
            gen_op_movl_T1_im(val);
1491
        } else {
1492
            gen_op_mov_TN_reg[ot][1][reg]();
1493
        }
1494

    
1495
        if (ot == OT_LONG) {
1496
            gen_op_imull_T0_T1();
1497
        } else {
1498
            gen_op_imulw_T0_T1();
1499
        }
1500
        gen_op_mov_reg_T0[ot][reg]();
1501
        s->cc_op = CC_OP_MUL;
1502
        break;
1503
        
1504
        /**************************/
1505
        /* push/pop */
1506
    case 0x50 ... 0x57: /* push */
1507
        gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1508
        gen_op_pushl_T0();
1509
        break;
1510
    case 0x58 ... 0x5f: /* pop */
1511
        gen_op_popl_T0();
1512
        gen_op_mov_reg_T0[OT_LONG][b & 7]();
1513
        break;
1514
    case 0x68: /* push Iv */
1515
    case 0x6a:
1516
        ot = dflag ? OT_LONG : OT_WORD;
1517
        if (b == 0x68)
1518
            val = insn_get(s, ot);
1519
        else
1520
            val = (int8_t)insn_get(s, OT_BYTE);
1521
        gen_op_movl_T0_im(val);
1522
        gen_op_pushl_T0();
1523
        break;
1524
    case 0x8f: /* pop Ev */
1525
        ot = dflag ? OT_LONG : OT_WORD;
1526
        modrm = ldub(s->pc++);
1527
        gen_op_popl_T0();
1528
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1529
        break;
1530
    case 0xc9: /* leave */
1531
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1532
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1533
        gen_op_popl_T0();
1534
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1535
        break;
1536
        /**************************/
1537
        /* mov */
1538
    case 0x88:
1539
    case 0x89: /* mov Gv, Ev */
1540
        if ((b & 1) == 0)
1541
            ot = OT_BYTE;
1542
        else
1543
            ot = dflag ? OT_LONG : OT_WORD;
1544
        modrm = ldub(s->pc++);
1545
        reg = (modrm >> 3) & 7;
1546
        
1547
        /* generate a generic store */
1548
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1549
        break;
1550
    case 0xc6:
1551
    case 0xc7: /* mov Ev, Iv */
1552
        if ((b & 1) == 0)
1553
            ot = OT_BYTE;
1554
        else
1555
            ot = dflag ? OT_LONG : OT_WORD;
1556
        modrm = ldub(s->pc++);
1557
        mod = (modrm >> 6) & 3;
1558
        if (mod != 3)
1559
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1560
        val = insn_get(s, ot);
1561
        gen_op_movl_T0_im(val);
1562
        if (mod != 3)
1563
            gen_op_st_T0_A0[ot]();
1564
        else
1565
            gen_op_mov_reg_T0[ot][modrm & 7]();
1566
        break;
1567
    case 0x8a:
1568
    case 0x8b: /* mov Ev, Gv */
1569
        if ((b & 1) == 0)
1570
            ot = OT_BYTE;
1571
        else
1572
            ot = dflag ? OT_LONG : OT_WORD;
1573
        modrm = ldub(s->pc++);
1574
        reg = (modrm >> 3) & 7;
1575
        
1576
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1577
        gen_op_mov_reg_T0[ot][reg]();
1578
        break;
1579

    
1580
    case 0x1b6: /* movzbS Gv, Eb */
1581
    case 0x1b7: /* movzwS Gv, Eb */
1582
    case 0x1be: /* movsbS Gv, Eb */
1583
    case 0x1bf: /* movswS Gv, Eb */
1584
        {
1585
            int d_ot;
1586
            /* d_ot is the size of destination */
1587
            d_ot = dflag + OT_WORD;
1588
            /* ot is the size of source */
1589
            ot = (b & 1) + OT_BYTE;
1590
            modrm = ldub(s->pc++);
1591
            reg = ((modrm >> 3) & 7) + OR_EAX;
1592
            mod = (modrm >> 6) & 3;
1593
            rm = modrm & 7;
1594
            
1595
            if (mod == 3) {
1596
                gen_op_mov_TN_reg[ot][0][rm]();
1597
                switch(ot | (b & 8)) {
1598
                case OT_BYTE:
1599
                    gen_op_movzbl_T0_T0();
1600
                    break;
1601
                case OT_BYTE | 8:
1602
                    gen_op_movsbl_T0_T0();
1603
                    break;
1604
                case OT_WORD:
1605
                    gen_op_movzwl_T0_T0();
1606
                    break;
1607
                default:
1608
                case OT_WORD | 8:
1609
                    gen_op_movswl_T0_T0();
1610
                    break;
1611
                }
1612
                gen_op_mov_reg_T0[d_ot][reg]();
1613
            } else {
1614
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1615
                if (b & 8) {
1616
                    gen_op_lds_T0_A0[ot]();
1617
                } else {
1618
                    gen_op_ldu_T0_A0[ot]();
1619
                }
1620
                gen_op_mov_reg_T0[d_ot][reg]();
1621
            }
1622
        }
1623
        break;
1624

    
1625
    case 0x8d: /* lea */
1626
        ot = dflag ? OT_LONG : OT_WORD;
1627
        modrm = ldub(s->pc++);
1628
        reg = (modrm >> 3) & 7;
1629

    
1630
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1631
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1632
        break;
1633
        
1634
    case 0xa0: /* mov EAX, Ov */
1635
    case 0xa1:
1636
    case 0xa2: /* mov Ov, EAX */
1637
    case 0xa3:
1638
        if ((b & 1) == 0)
1639
            ot = OT_BYTE;
1640
        else
1641
            ot = dflag ? OT_LONG : OT_WORD;
1642
        if (s->aflag)
1643
            offset_addr = insn_get(s, OT_LONG);
1644
        else
1645
            offset_addr = insn_get(s, OT_WORD);
1646
        gen_op_movl_A0_im(offset_addr);
1647
        if ((b & 2) == 0) {
1648
            gen_op_ld_T0_A0[ot]();
1649
            gen_op_mov_reg_T0[ot][R_EAX]();
1650
        } else {
1651
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1652
            gen_op_st_T0_A0[ot]();
1653
        }
1654
        break;
1655

    
1656
    case 0xb0 ... 0xb7: /* mov R, Ib */
1657
        val = insn_get(s, OT_BYTE);
1658
        gen_op_movl_T0_im(val);
1659
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1660
        break;
1661
    case 0xb8 ... 0xbf: /* mov R, Iv */
1662
        ot = dflag ? OT_LONG : OT_WORD;
1663
        val = insn_get(s, ot);
1664
        reg = OR_EAX + (b & 7);
1665
        gen_op_movl_T0_im(val);
1666
        gen_op_mov_reg_T0[ot][reg]();
1667
        break;
1668

    
1669
    case 0x91 ... 0x97: /* xchg R, EAX */
1670
        ot = dflag ? OT_LONG : OT_WORD;
1671
        reg = b & 7;
1672
        gen_op_mov_TN_reg[ot][0][reg]();
1673
        gen_op_mov_TN_reg[ot][1][R_EAX]();
1674
        gen_op_mov_reg_T0[ot][R_EAX]();
1675
        gen_op_mov_reg_T1[ot][reg]();
1676
        break;
1677
    case 0x86:
1678
    case 0x87: /* xchg Ev, Gv */
1679
        if ((b & 1) == 0)
1680
            ot = OT_BYTE;
1681
        else
1682
            ot = dflag ? OT_LONG : OT_WORD;
1683
        modrm = ldub(s->pc++);
1684
        reg = (modrm >> 3) & 7;
1685

    
1686
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1687
        gen_op_mov_TN_reg[ot][0][reg]();
1688
        gen_op_ld_T1_A0[ot]();
1689
        gen_op_st_T0_A0[ot]();
1690
        gen_op_mov_reg_T1[ot][reg]();
1691
        break;
1692
        
1693
        /************************/
1694
        /* shifts */
1695
    case 0xc0:
1696
    case 0xc1:
1697
        /* shift Ev,Ib */
1698
        shift = 2;
1699
    grp2:
1700
        {
1701
            if ((b & 1) == 0)
1702
                ot = OT_BYTE;
1703
            else
1704
                ot = dflag ? OT_LONG : OT_WORD;
1705
            
1706
            modrm = ldub(s->pc++);
1707
            mod = (modrm >> 6) & 3;
1708
            rm = modrm & 7;
1709
            op = (modrm >> 3) & 7;
1710
            
1711
            if (mod != 3) {
1712
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1713
                gen_op_ld_T0_A0[ot]();
1714
                opreg = OR_TMP0;
1715
            } else {
1716
                opreg = rm + OR_EAX;
1717
            }
1718

    
1719
            /* simpler op */
1720
            if (shift == 0) {
1721
                gen_shift(s, op, ot, opreg, OR_ECX);
1722
            } else {
1723
                if (shift == 2) {
1724
                    shift = ldub(s->pc++);
1725
                }
1726
                gen_shifti(s, op, ot, opreg, shift);
1727
            }
1728

    
1729
            if (mod != 3) {
1730
                gen_op_st_T0_A0[ot]();
1731
            }
1732
        }
1733
        break;
1734
    case 0xd0:
1735
    case 0xd1:
1736
        /* shift Ev,1 */
1737
        shift = 1;
1738
        goto grp2;
1739
    case 0xd2:
1740
    case 0xd3:
1741
        /* shift Ev,cl */
1742
        shift = 0;
1743
        goto grp2;
1744

    
1745
    case 0x1a4: /* shld imm */
1746
        op = 0;
1747
        shift = 1;
1748
        goto do_shiftd;
1749
    case 0x1a5: /* shld cl */
1750
        op = 0;
1751
        shift = 0;
1752
        goto do_shiftd;
1753
    case 0x1ac: /* shrd imm */
1754
        op = 1;
1755
        shift = 1;
1756
        goto do_shiftd;
1757
    case 0x1ad: /* shrd cl */
1758
        op = 1;
1759
        shift = 0;
1760
    do_shiftd:
1761
        ot = dflag ? OT_LONG : OT_WORD;
1762
        modrm = ldub(s->pc++);
1763
        mod = (modrm >> 6) & 3;
1764
        rm = modrm & 7;
1765
        reg = (modrm >> 3) & 7;
1766
        
1767
        if (mod != 3) {
1768
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1769
            gen_op_ld_T0_A0[ot]();
1770
        } else {
1771
            gen_op_mov_TN_reg[ot][0][rm]();
1772
        }
1773
        gen_op_mov_TN_reg[ot][1][reg]();
1774
        
1775
        if (shift) {
1776
            val = ldub(s->pc++);
1777
            val &= 0x1f;
1778
            if (val) {
1779
                gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1780
                if (op == 0 && ot != OT_WORD)
1781
                    s->cc_op = CC_OP_SHLB + ot;
1782
                else
1783
                    s->cc_op = CC_OP_SARB + ot;
1784
            }
1785
        } else {
1786
            if (s->cc_op != CC_OP_DYNAMIC)
1787
                gen_op_set_cc_op(s->cc_op);
1788
            gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1789
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1790
        }
1791
        if (mod != 3) {
1792
            gen_op_st_T0_A0[ot]();
1793
        } else {
1794
            gen_op_mov_reg_T0[ot][rm]();
1795
        }
1796
        break;
1797

    
1798
        /************************/
1799
        /* floats */
1800
    case 0xd8 ... 0xdf: 
1801
        modrm = ldub(s->pc++);
1802
        mod = (modrm >> 6) & 3;
1803
        rm = modrm & 7;
1804
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1805
        
1806
        if (mod != 3) {
1807
            /* memory op */
1808
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1809
            switch(op) {
1810
            case 0x00 ... 0x07: /* fxxxs */
1811
            case 0x10 ... 0x17: /* fixxxl */
1812
            case 0x20 ... 0x27: /* fxxxl */
1813
            case 0x30 ... 0x37: /* fixxx */
1814
                {
1815
                    int op1;
1816
                    op1 = op & 7;
1817

    
1818
                    switch(op >> 4) {
1819
                    case 0:
1820
                        gen_op_flds_FT0_A0();
1821
                        break;
1822
                    case 1:
1823
                        gen_op_fildl_FT0_A0();
1824
                        break;
1825
                    case 2:
1826
                        gen_op_fldl_FT0_A0();
1827
                        break;
1828
                    case 3:
1829
                    default:
1830
                        gen_op_fild_FT0_A0();
1831
                        break;
1832
                    }
1833
                    
1834
                    gen_op_fp_arith_ST0_FT0[op1]();
1835
                    if (op1 == 3) {
1836
                        /* fcomp needs pop */
1837
                        gen_op_fpop();
1838
                    }
1839
                }
1840
                break;
1841
            case 0x08: /* flds */
1842
            case 0x0a: /* fsts */
1843
            case 0x0b: /* fstps */
1844
            case 0x18: /* fildl */
1845
            case 0x1a: /* fistl */
1846
            case 0x1b: /* fistpl */
1847
            case 0x28: /* fldl */
1848
            case 0x2a: /* fstl */
1849
            case 0x2b: /* fstpl */
1850
            case 0x38: /* filds */
1851
            case 0x3a: /* fists */
1852
            case 0x3b: /* fistps */
1853
                
1854
                switch(op & 7) {
1855
                case 0:
1856
                    gen_op_fpush();
1857
                    switch(op >> 4) {
1858
                    case 0:
1859
                        gen_op_flds_ST0_A0();
1860
                        break;
1861
                    case 1:
1862
                        gen_op_fildl_ST0_A0();
1863
                        break;
1864
                    case 2:
1865
                        gen_op_fldl_ST0_A0();
1866
                        break;
1867
                    case 3:
1868
                    default:
1869
                        gen_op_fild_ST0_A0();
1870
                        break;
1871
                    }
1872
                    break;
1873
                default:
1874
                    switch(op >> 4) {
1875
                    case 0:
1876
                        gen_op_fsts_ST0_A0();
1877
                        break;
1878
                    case 1:
1879
                        gen_op_fistl_ST0_A0();
1880
                        break;
1881
                    case 2:
1882
                        gen_op_fstl_ST0_A0();
1883
                        break;
1884
                    case 3:
1885
                    default:
1886
                        gen_op_fist_ST0_A0();
1887
                        break;
1888
                    }
1889
                    if ((op & 7) == 3)
1890
                        gen_op_fpop();
1891
                    break;
1892
                }
1893
                break;
1894
            case 0x0d: /* fldcw mem */
1895
                gen_op_fldcw_A0();
1896
                break;
1897
            case 0x0f: /* fnstcw mem */
1898
                gen_op_fnstcw_A0();
1899
                break;
1900
            case 0x1d: /* fldt mem */
1901
                gen_op_fpush();
1902
                gen_op_fldt_ST0_A0();
1903
                break;
1904
            case 0x1f: /* fstpt mem */
1905
                gen_op_fstt_ST0_A0();
1906
                gen_op_fpop();
1907
                break;
1908
            case 0x2f: /* fnstsw mem */
1909
                gen_op_fnstsw_A0();
1910
                break;
1911
            case 0x3c: /* fbld */
1912
                gen_op_fpush();
1913
                gen_op_fbld_ST0_A0();
1914
                break;
1915
            case 0x3e: /* fbstp */
1916
                gen_op_fbst_ST0_A0();
1917
                gen_op_fpop();
1918
                break;
1919
            case 0x3d: /* fildll */
1920
                gen_op_fpush();
1921
                gen_op_fildll_ST0_A0();
1922
                break;
1923
            case 0x3f: /* fistpll */
1924
                gen_op_fistll_ST0_A0();
1925
                gen_op_fpop();
1926
                break;
1927
            default:
1928
                error("unhandled FPm [op=0x%02x]\n", op);
1929
                return -1;
1930
            }
1931
        } else {
1932
            /* register float ops */
1933
            opreg = rm;
1934

    
1935
            switch(op) {
1936
            case 0x08: /* fld sti */
1937
                gen_op_fpush();
1938
                gen_op_fmov_ST0_STN((opreg + 1) & 7);
1939
                break;
1940
            case 0x09: /* fxchg sti */
1941
                gen_op_fxchg_ST0_STN(opreg);
1942
                break;
1943
            case 0x0a: /* grp d9/2 */
1944
                switch(rm) {
1945
                case 0: /* fnop */
1946
                    break;
1947
                default:
1948
                    error("unhandled FP GRP d9/2\n");
1949
                    return -1;
1950
                }
1951
                break;
1952
            case 0x0c: /* grp d9/4 */
1953
                switch(rm) {
1954
                case 0: /* fchs */
1955
                    gen_op_fchs_ST0();
1956
                    break;
1957
                case 1: /* fabs */
1958
                    gen_op_fabs_ST0();
1959
                    break;
1960
                case 4: /* ftst */
1961
                    gen_op_fldz_FT0();
1962
                    gen_op_fcom_ST0_FT0();
1963
                    break;
1964
                case 5: /* fxam */
1965
                    gen_op_fxam_ST0();
1966
                    break;
1967
                default:
1968
                    return -1;
1969
                }
1970
                break;
1971
            case 0x0d: /* grp d9/5 */
1972
                {
1973
                    switch(rm) {
1974
                    case 0:
1975
                        gen_op_fpush();
1976
                        gen_op_fld1_ST0();
1977
                        break;
1978
                    case 1:
1979
                        gen_op_fpush();
1980
                        gen_op_fldl2t_ST0();
1981
                        break;
1982
                    case 2:
1983
                        gen_op_fpush();
1984
                        gen_op_fldl2e_ST0();
1985
                        break;
1986
                    case 3:
1987
                        gen_op_fpush();
1988
                        gen_op_fldpi_ST0();
1989
                        break;
1990
                    case 4:
1991
                        gen_op_fpush();
1992
                        gen_op_fldlg2_ST0();
1993
                        break;
1994
                    case 5:
1995
                        gen_op_fpush();
1996
                        gen_op_fldln2_ST0();
1997
                        break;
1998
                    case 6:
1999
                        gen_op_fpush();
2000
                        gen_op_fldz_ST0();
2001
                        break;
2002
                    default:
2003
                        return -1;
2004
                    }
2005
                }
2006
                break;
2007
            case 0x0e: /* grp d9/6 */
2008
                switch(rm) {
2009
                case 0: /* f2xm1 */
2010
                    gen_op_f2xm1();
2011
                    break;
2012
                case 1: /* fyl2x */
2013
                    gen_op_fyl2x();
2014
                    break;
2015
                case 2: /* fptan */
2016
                    gen_op_fptan();
2017
                    break;
2018
                case 3: /* fpatan */
2019
                    gen_op_fpatan();
2020
                    break;
2021
                case 4: /* fxtract */
2022
                    gen_op_fxtract();
2023
                    break;
2024
                case 5: /* fprem1 */
2025
                    gen_op_fprem1();
2026
                    break;
2027
                case 6: /* fdecstp */
2028
                    gen_op_fdecstp();
2029
                    break;
2030
                default:
2031
                case 7: /* fincstp */
2032
                    gen_op_fincstp();
2033
                    break;
2034
                }
2035
                break;
2036
            case 0x0f: /* grp d9/7 */
2037
                switch(rm) {
2038
                case 0: /* fprem */
2039
                    gen_op_fprem();
2040
                    break;
2041
                case 1: /* fyl2xp1 */
2042
                    gen_op_fyl2xp1();
2043
                    break;
2044
                case 2: /* fsqrt */
2045
                    gen_op_fsqrt();
2046
                    break;
2047
                case 3: /* fsincos */
2048
                    gen_op_fsincos();
2049
                    break;
2050
                case 5: /* fscale */
2051
                    gen_op_fscale();
2052
                    break;
2053
                case 4: /* frndint */
2054
                    gen_op_frndint();
2055
                    break;
2056
                case 6: /* fsin */
2057
                    gen_op_fsin();
2058
                    break;
2059
                default:
2060
                case 7: /* fcos */
2061
                    gen_op_fcos();
2062
                    break;
2063
                }
2064
                break;
2065
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2066
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2067
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2068
                {
2069
                    int op1;
2070
                    
2071
                    op1 = op & 7;
2072
                    if (op >= 0x20) {
2073
                        gen_op_fp_arith_STN_ST0[op1](opreg);
2074
                        if (op >= 0x30)
2075
                            gen_op_fpop();
2076
                    } else {
2077
                        gen_op_fmov_FT0_STN(opreg);
2078
                        gen_op_fp_arith_ST0_FT0[op1]();
2079
                    }
2080
                }
2081
                break;
2082
            case 0x02: /* fcom */
2083
                gen_op_fmov_FT0_STN(opreg);
2084
                gen_op_fcom_ST0_FT0();
2085
                break;
2086
            case 0x03: /* fcomp */
2087
                gen_op_fmov_FT0_STN(opreg);
2088
                gen_op_fcom_ST0_FT0();
2089
                gen_op_fpop();
2090
                break;
2091
            case 0x15: /* da/5 */
2092
                switch(rm) {
2093
                case 1: /* fucompp */
2094
                    gen_op_fmov_FT0_STN(1);
2095
                    gen_op_fucom_ST0_FT0();
2096
                    gen_op_fpop();
2097
                    gen_op_fpop();
2098
                    break;
2099
                default:
2100
                    return -1;
2101
                }
2102
                break;
2103
            case 0x2a: /* fst sti */
2104
                gen_op_fmov_STN_ST0(opreg);
2105
                break;
2106
            case 0x2b: /* fstp sti */
2107
                gen_op_fmov_STN_ST0(opreg);
2108
                gen_op_fpop();
2109
                break;
2110
            case 0x2c: /* fucom st(i) */
2111
                gen_op_fmov_FT0_STN(opreg);
2112
                gen_op_fucom_ST0_FT0();
2113
                break;
2114
            case 0x2d: /* fucomp st(i) */
2115
                gen_op_fmov_FT0_STN(opreg);
2116
                gen_op_fucom_ST0_FT0();
2117
                gen_op_fpop();
2118
                break;
2119
            case 0x33: /* de/3 */
2120
                switch(rm) {
2121
                case 1: /* fcompp */
2122
                    gen_op_fmov_FT0_STN(1);
2123
                    gen_op_fcom_ST0_FT0();
2124
                    gen_op_fpop();
2125
                    gen_op_fpop();
2126
                    break;
2127
                default:
2128
                    return -1;
2129
                }
2130
                break;
2131
            case 0x3c: /* df/4 */
2132
                switch(rm) {
2133
                case 0:
2134
                    gen_op_fnstsw_EAX();
2135
                    break;
2136
                default:
2137
                    error("unhandled FP %x df/4\n", rm);
2138
                    return -1;
2139
                }
2140
                break;
2141
            default:
2142
                error("unhandled FPr [op=0x%x]\n", op);
2143
                return -1;
2144
            }
2145
        }
2146
        break;
2147
        /************************/
2148
        /* string ops */
2149
    case 0xa4: /* movsS */
2150
    case 0xa5:
2151
        if ((b & 1) == 0)
2152
            ot = OT_BYTE;
2153
        else
2154
            ot = dflag ? OT_LONG : OT_WORD;
2155
        if (prefixes & PREFIX_REPZ) {
2156
            gen_op_movs[3 + ot]();
2157
        } else {
2158
            gen_op_movs[ot]();
2159
        }
2160
        break;
2161
        
2162
    case 0xaa: /* stosS */
2163
    case 0xab:
2164
        if ((b & 1) == 0)
2165
            ot = OT_BYTE;
2166
        else
2167
            ot = dflag ? OT_LONG : OT_WORD;
2168
        if (prefixes & PREFIX_REPZ) {
2169
            gen_op_stos[3 + ot]();
2170
        } else {
2171
            gen_op_stos[ot]();
2172
        }
2173
        break;
2174
    case 0xac: /* lodsS */
2175
    case 0xad:
2176
        if ((b & 1) == 0)
2177
            ot = OT_BYTE;
2178
        else
2179
            ot = dflag ? OT_LONG : OT_WORD;
2180
        if (prefixes & PREFIX_REPZ) {
2181
            gen_op_lods[3 + ot]();
2182
        } else {
2183
            gen_op_lods[ot]();
2184
        }
2185
        break;
2186
    case 0xae: /* scasS */
2187
    case 0xaf:
2188
        if ((b & 1) == 0)
2189
            ot = OT_BYTE;
2190
        else
2191
            ot = dflag ? OT_LONG : OT_WORD;
2192
        if (prefixes & PREFIX_REPNZ) {
2193
            if (s->cc_op != CC_OP_DYNAMIC)
2194
                gen_op_set_cc_op(s->cc_op);
2195
            gen_op_scas[6 + ot]();
2196
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2197
        } else if (prefixes & PREFIX_REPZ) {
2198
            if (s->cc_op != CC_OP_DYNAMIC)
2199
                gen_op_set_cc_op(s->cc_op);
2200
            gen_op_scas[3 + ot]();
2201
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2202
        } else {
2203
            gen_op_scas[ot]();
2204
            s->cc_op = CC_OP_SUBB + ot;
2205
        }
2206
        break;
2207

    
2208
    case 0xa6: /* cmpsS */
2209
    case 0xa7:
2210
        if ((b & 1) == 0)
2211
            ot = OT_BYTE;
2212
        else
2213
            ot = dflag ? OT_LONG : OT_WORD;
2214
        if (prefixes & PREFIX_REPNZ) {
2215
            if (s->cc_op != CC_OP_DYNAMIC)
2216
                gen_op_set_cc_op(s->cc_op);
2217
            gen_op_cmps[6 + ot]();
2218
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2219
        } else if (prefixes & PREFIX_REPZ) {
2220
            if (s->cc_op != CC_OP_DYNAMIC)
2221
                gen_op_set_cc_op(s->cc_op);
2222
            gen_op_cmps[3 + ot]();
2223
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2224
        } else {
2225
            gen_op_cmps[ot]();
2226
            s->cc_op = CC_OP_SUBB + ot;
2227
        }
2228
        break;
2229
        
2230
        /************************/
2231
        /* port I/O */
2232
    case 0x6c: /* insS */
2233
    case 0x6d:
2234
        if ((b & 1) == 0)
2235
            ot = OT_BYTE;
2236
        else
2237
            ot = dflag ? OT_LONG : OT_WORD;
2238
        if (prefixes & PREFIX_REPZ) {
2239
            gen_op_ins[3 + ot]();
2240
        } else {
2241
            gen_op_ins[ot]();
2242
        }
2243
        break;
2244
    case 0x6e: /* outsS */
2245
    case 0x6f:
2246
        if ((b & 1) == 0)
2247
            ot = OT_BYTE;
2248
        else
2249
            ot = dflag ? OT_LONG : OT_WORD;
2250
        if (prefixes & PREFIX_REPZ) {
2251
            gen_op_outs[3 + ot]();
2252
        } else {
2253
            gen_op_outs[ot]();
2254
        }
2255
        break;
2256
    case 0xe4:
2257
    case 0xe5:
2258
        if ((b & 1) == 0)
2259
            ot = OT_BYTE;
2260
        else
2261
            ot = dflag ? OT_LONG : OT_WORD;
2262
        val = ldub(s->pc++);
2263
        gen_op_movl_T0_im(val);
2264
        gen_op_in[ot]();
2265
        gen_op_mov_reg_T1[ot][R_EAX]();
2266
        break;
2267
    case 0xe6:
2268
    case 0xe7:
2269
        if ((b & 1) == 0)
2270
            ot = OT_BYTE;
2271
        else
2272
            ot = dflag ? OT_LONG : OT_WORD;
2273
        val = ldub(s->pc++);
2274
        gen_op_movl_T0_im(val);
2275
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2276
        gen_op_out[ot]();
2277
        break;
2278
    case 0xec:
2279
    case 0xed:
2280
        if ((b & 1) == 0)
2281
            ot = OT_BYTE;
2282
        else
2283
            ot = dflag ? OT_LONG : OT_WORD;
2284
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2285
        gen_op_in[ot]();
2286
        gen_op_mov_reg_T1[ot][R_EAX]();
2287
        break;
2288
    case 0xee:
2289
    case 0xef:
2290
        if ((b & 1) == 0)
2291
            ot = OT_BYTE;
2292
        else
2293
            ot = dflag ? OT_LONG : OT_WORD;
2294
        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2295
        gen_op_mov_TN_reg[ot][1][R_EAX]();
2296
        gen_op_out[ot]();
2297
        break;
2298

    
2299
        /************************/
2300
        /* control */
2301
    case 0xc2: /* ret im */
2302
        /* XXX: handle stack pop ? */
2303
        val = ldsw(s->pc);
2304
        s->pc += 2;
2305
        gen_op_popl_T0();
2306
        gen_op_addl_ESP_im(val);
2307
        gen_op_jmp_T0();
2308
        *is_jmp_ptr = 1;
2309
        break;
2310
    case 0xc3: /* ret */
2311
        gen_op_popl_T0();
2312
        gen_op_jmp_T0();
2313
        *is_jmp_ptr = 1;
2314
        break;
2315
    case 0xe8: /* call */
2316
        val = insn_get(s, OT_LONG);
2317
        val += (long)s->pc;
2318
        gen_op_movl_T1_im((long)s->pc);
2319
        gen_op_pushl_T1();
2320
        gen_op_jmp_im(val);
2321
        *is_jmp_ptr = 1;
2322
        break;
2323
    case 0xe9: /* jmp */
2324
        val = insn_get(s, OT_LONG);
2325
        val += (long)s->pc;
2326
        gen_op_jmp_im(val);
2327
        *is_jmp_ptr = 1;
2328
        break;
2329
    case 0xeb: /* jmp Jb */
2330
        val = (int8_t)insn_get(s, OT_BYTE);
2331
        val += (long)s->pc;
2332
        gen_op_jmp_im(val);
2333
        *is_jmp_ptr = 1;
2334
        break;
2335
    case 0x70 ... 0x7f: /* jcc Jb */
2336
        val = (int8_t)insn_get(s, OT_BYTE);
2337
        val += (long)s->pc;
2338
        goto do_jcc;
2339
    case 0x180 ... 0x18f: /* jcc Jv */
2340
        if (dflag) {
2341
            val = insn_get(s, OT_LONG);
2342
        } else {
2343
            val = (int16_t)insn_get(s, OT_WORD); 
2344
        }
2345
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2346
    do_jcc:
2347
        gen_jcc(s, b, val);
2348
        *is_jmp_ptr = 1;
2349
        break;
2350

    
2351
    case 0x190 ... 0x19f:
2352
        modrm = ldub(s->pc++);
2353
        gen_setcc(s, b);
2354
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2355
        break;
2356

    
2357
        /************************/
2358
        /* flags */
2359
    case 0x9c: /* pushf */
2360
        if (s->cc_op != CC_OP_DYNAMIC)
2361
            gen_op_set_cc_op(s->cc_op);
2362
        gen_op_movl_T0_eflags();
2363
        gen_op_pushl_T0();
2364
        break;
2365
    case 0x9d: /* popf */
2366
        gen_op_popl_T0();
2367
        gen_op_movl_eflags_T0();
2368
        s->cc_op = CC_OP_EFLAGS;
2369
        break;
2370
    case 0x9e: /* sahf */
2371
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2372
        if (s->cc_op != CC_OP_DYNAMIC)
2373
            gen_op_set_cc_op(s->cc_op);
2374
        gen_op_movb_eflags_T0();
2375
        s->cc_op = CC_OP_EFLAGS;
2376
        break;
2377
    case 0x9f: /* lahf */
2378
        if (s->cc_op != CC_OP_DYNAMIC)
2379
            gen_op_set_cc_op(s->cc_op);
2380
        gen_op_movl_T0_eflags();
2381
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2382
        break;
2383
    case 0xf5: /* cmc */
2384
        if (s->cc_op != CC_OP_DYNAMIC)
2385
            gen_op_set_cc_op(s->cc_op);
2386
        gen_op_cmc();
2387
        s->cc_op = CC_OP_EFLAGS;
2388
        break;
2389
    case 0xf8: /* clc */
2390
        if (s->cc_op != CC_OP_DYNAMIC)
2391
            gen_op_set_cc_op(s->cc_op);
2392
        gen_op_clc();
2393
        s->cc_op = CC_OP_EFLAGS;
2394
        break;
2395
    case 0xf9: /* stc */
2396
        if (s->cc_op != CC_OP_DYNAMIC)
2397
            gen_op_set_cc_op(s->cc_op);
2398
        gen_op_stc();
2399
        s->cc_op = CC_OP_EFLAGS;
2400
        break;
2401
    case 0xfc: /* cld */
2402
        gen_op_cld();
2403
        break;
2404
    case 0xfd: /* std */
2405
        gen_op_std();
2406
        break;
2407

    
2408
        /************************/
2409
        /* bit operations */
2410
    case 0x1ba: /* bt/bts/btr/btc Gv, im */
2411
        ot = dflag ? OT_LONG : OT_WORD;
2412
        modrm = ldub(s->pc++);
2413
        op = (modrm >> 3) & 7;
2414
        mod = (modrm >> 6) & 3;
2415
        rm = modrm & 7;
2416
        if (mod != 3) {
2417
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2418
            gen_op_ld_T0_A0[ot]();
2419
        } else {
2420
            gen_op_mov_TN_reg[ot][0][rm]();
2421
        }
2422
        /* load shift */
2423
        val = ldub(s->pc++);
2424
        gen_op_movl_T1_im(val);
2425
        if (op < 4)
2426
            return -1;
2427
        op -= 4;
2428
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2429
        s->cc_op = CC_OP_SARB + ot;
2430
        if (op != 0) {
2431
            if (mod != 3)
2432
                gen_op_st_T0_A0[ot]();
2433
            else
2434
                gen_op_mov_reg_T0[ot][rm]();
2435
        }
2436
        break;
2437
    case 0x1a3: /* bt Gv, Ev */
2438
        op = 0;
2439
        goto do_btx;
2440
    case 0x1ab: /* bts */
2441
        op = 1;
2442
        goto do_btx;
2443
    case 0x1b3: /* btr */
2444
        op = 2;
2445
        goto do_btx;
2446
    case 0x1bb: /* btc */
2447
        op = 3;
2448
    do_btx:
2449
        ot = dflag ? OT_LONG : OT_WORD;
2450
        modrm = ldub(s->pc++);
2451
        reg = (modrm >> 3) & 7;
2452
        mod = (modrm >> 6) & 3;
2453
        rm = modrm & 7;
2454
        gen_op_mov_TN_reg[OT_LONG][1][reg]();
2455
        if (mod != 3) {
2456
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2457
            /* specific case: we need to add a displacement */
2458
            if (ot == OT_WORD)
2459
                gen_op_add_bitw_A0_T1();
2460
            else
2461
                gen_op_add_bitl_A0_T1();
2462
            gen_op_ld_T0_A0[ot]();
2463
        } else {
2464
            gen_op_mov_TN_reg[ot][0][rm]();
2465
        }
2466
        gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2467
        s->cc_op = CC_OP_SARB + ot;
2468
        if (op != 0) {
2469
            if (mod != 3)
2470
                gen_op_st_T0_A0[ot]();
2471
            else
2472
                gen_op_mov_reg_T0[ot][rm]();
2473
        }
2474
        break;
2475
    case 0x1bc: /* bsf */
2476
    case 0x1bd: /* bsr */
2477
        ot = dflag ? OT_LONG : OT_WORD;
2478
        modrm = ldub(s->pc++);
2479
        reg = (modrm >> 3) & 7;
2480
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2481
        gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2482
        /* NOTE: we always write back the result. Intel doc says it is
2483
           undefined if T0 == 0 */
2484
        gen_op_mov_reg_T0[ot][reg]();
2485
        s->cc_op = CC_OP_LOGICB + ot;
2486
        break;
2487
        /************************/
2488
        /* misc */
2489
    case 0x90: /* nop */
2490
        break;
2491
    case 0xcc: /* int3 */
2492
        gen_op_int3((long)pc_start);
2493
        *is_jmp_ptr = 1;
2494
        break;
2495
    case 0xcd: /* int N */
2496
        val = ldub(s->pc++);
2497
        /* XXX: currently we ignore the interrupt number */
2498
        gen_op_int_im((long)pc_start);
2499
        *is_jmp_ptr = 1;
2500
        break;
2501
    case 0xce: /* into */
2502
        if (s->cc_op != CC_OP_DYNAMIC)
2503
            gen_op_set_cc_op(s->cc_op);
2504
        gen_op_into((long)pc_start, (long)s->pc);
2505
        *is_jmp_ptr = 1;
2506
        break;
2507
    case 0x1c8 ... 0x1cf: /* bswap reg */
2508
      reg = b & 7;
2509
      gen_op_mov_TN_reg[OT_LONG][0][reg]();
2510
      gen_op_bswapl_T0();
2511
      gen_op_mov_reg_T0[OT_LONG][reg]();
2512
      break;
2513
      
2514
#if 0
2515
    case 0x1a2: /* cpuid */
2516
        gen_insn0(OP_ASM);
2517
        break;
2518
#endif
2519
    default:
2520
        error("unknown opcode %x", b);
2521
        return -1;
2522
    }
2523
    return (long)s->pc;
2524
}
2525

    
2526
/* return the next pc */
2527
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
2528
                     int *gen_code_size_ptr, uint8_t *pc_start)
2529
{
2530
    DisasContext dc1, *dc = &dc1;
2531
    uint8_t *gen_code_end, *pc_ptr;
2532
    int is_jmp;
2533
    long ret;
2534
#ifdef DEBUG_DISAS
2535
    struct disassemble_info disasm_info;
2536
#endif
2537

    
2538
    dc->cc_op = CC_OP_DYNAMIC;
2539
    gen_code_ptr = gen_code_buf;
2540
    gen_code_end = gen_code_buf + max_code_size - 4096;
2541
    gen_start();
2542

    
2543
    is_jmp = 0;
2544
    pc_ptr = pc_start;
2545
    do {
2546
        ret = disas_insn(dc, pc_ptr, &is_jmp);
2547
        if (ret == -1) 
2548
            error("unknown instruction at PC=0x%x B=%02x %02x", 
2549
                  pc_ptr, pc_ptr[0], pc_ptr[1]);
2550
        pc_ptr = (void *)ret;
2551
    } while (!is_jmp && gen_code_ptr < gen_code_end);
2552
    /* we must store the eflags state if it is not already done */
2553
    if (dc->cc_op != CC_OP_DYNAMIC)
2554
        gen_op_set_cc_op(dc->cc_op);
2555
    if (!is_jmp) {
2556
        /* we add an additionnal jmp to update the simulated PC */
2557
        gen_op_jmp_im(ret);
2558
    }
2559
    gen_end();
2560
    *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2561

    
2562
#ifdef DEBUG_DISAS
2563
    if (loglevel) {
2564
        uint8_t *pc;
2565
        int count;
2566

    
2567
        INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2568
#if 0        
2569
        disasm_info.flavour = bfd_get_flavour (abfd);
2570
        disasm_info.arch = bfd_get_arch (abfd);
2571
        disasm_info.mach = bfd_get_mach (abfd);
2572
#endif
2573
#ifdef WORDS_BIGENDIAN
2574
        disasm_info.endian = BFD_ENDIAN_BIG;
2575
#else
2576
        disasm_info.endian = BFD_ENDIAN_LITTLE;
2577
#endif        
2578
        fprintf(logfile, "IN:\n");
2579
        disasm_info.buffer = pc_start;
2580
        disasm_info.buffer_vma = (unsigned long)pc_start;
2581
        disasm_info.buffer_length = pc_ptr - pc_start;
2582
        pc = pc_start;
2583
        while (pc < pc_ptr) {
2584
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2585
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2586
            fprintf(logfile, "\n");
2587
            pc += count;
2588
        }
2589
        fprintf(logfile, "\n");
2590
        
2591
        pc = gen_code_buf;
2592
        disasm_info.buffer = pc;
2593
        disasm_info.buffer_vma = (unsigned long)pc;
2594
        disasm_info.buffer_length = *gen_code_size_ptr;
2595
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2596
        while (pc < gen_code_ptr) {
2597
            fprintf(logfile, "0x%08lx:  ", (long)pc);
2598
            count = print_insn_i386((unsigned long)pc, &disasm_info);
2599
            fprintf(logfile, "\n");
2600
            pc += count;
2601
        }
2602
        fprintf(logfile, "\n");
2603
    }
2604
#endif
2605
    return 0;
2606
}
2607

    
2608
CPUX86State *cpu_x86_init(void)
2609
{
2610
    CPUX86State *env;
2611
    int i;
2612

    
2613
    cpu_x86_tblocks_init();
2614

    
2615
    env = malloc(sizeof(CPUX86State));
2616
    if (!env)
2617
        return NULL;
2618
    memset(env, 0, sizeof(CPUX86State));
2619
    /* basic FPU init */
2620
    for(i = 0;i < 8; i++)
2621
        env->fptags[i] = 1;
2622
    env->fpuc = 0x37f;
2623
    /* flags setup */
2624
    env->cc_op = CC_OP_EFLAGS;
2625
    env->df = 1;
2626
    return env;
2627
}
2628

    
2629
void cpu_x86_close(CPUX86State *env)
2630
{
2631
    free(env);
2632
}