Statistics
| Branch: | Revision:

root / translate-i386.c @ 367e86e8

History | View | Annotate | Download (55 kB)

1
#include <stdarg.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <string.h>
5
#include <inttypes.h>
6
#include <assert.h>
7

    
8
#include "cpu-i386.h"
9

    
10
static uint8_t *gen_code_ptr;
11
int __op_param1, __op_param2, __op_param3;
12

    
13
/* supress that */
14
static void error(const char *fmt, ...)
15
{
16
    va_list ap;
17

    
18
    va_start(ap, fmt);
19
    vfprintf(stderr, fmt, ap);
20
    va_end(ap);
21
    exit(1);
22
}
23

    
24
#define PREFIX_REPZ 1
25
#define PREFIX_REPNZ 2
26
#define PREFIX_LOCK 4
27
#define PREFIX_CS 8
28
#define PREFIX_SS 0x10
29
#define PREFIX_DS 0x20
30
#define PREFIX_ES 0x40
31
#define PREFIX_FS 0x80
32
#define PREFIX_GS 0x100
33
#define PREFIX_DATA 0x200
34
#define PREFIX_ADR 0x400
35
#define PREFIX_FWAIT 0x800
36

    
37
typedef struct DisasContext {
38
    /* current insn context */
39
    int prefix;
40
    int aflag, dflag;
41
    uint8_t *pc; /* current pc */
42
    uint8_t *runtime_pc; /* current pc in the runtime generated code */
43
    int cc_op; /* current CC operation */
44
    int f_st;
45
} DisasContext;
46

    
47
/* i386 arith/logic operations */
48
enum {
49
    OP_ADDL, 
50
    OP_ORL, 
51
    OP_ADCL, 
52
    OP_SBBL,
53
    OP_ANDL, 
54
    OP_SUBL, 
55
    OP_XORL, 
56
    OP_CMPL,
57
};
58

    
59
/* i386 shift ops */
60
enum {
61
    OP_ROL, 
62
    OP_ROR, 
63
    OP_RCL, 
64
    OP_RCR, 
65
    OP_SHL, 
66
    OP_SHR, 
67
    OP_SHL1, /* undocumented */
68
    OP_SAR = 7,
69
};
70

    
71

    
72
static const int fp_ops[8] = {
73
#if 0
74
    OP_FADDQ, OP_FMULQ, OP_CMP, OP_CMP,
75
    OP_FSUBQ, OP_FSUBQ, OP_FDIVQ, OP_FDIVQ
76
#endif
77
};
78

    
79
extern char cc_table, rclw_table, rclb_table;
80
extern char helper_rcll_T0_T1_cc;
81
extern char __udivdi3, __umoddi3;
82

    
83
#include "op-i386.h"
84

    
85
/* operand size */
86
enum {
87
    OT_BYTE = 0,
88
    OT_WORD,
89
    OT_LONG, 
90
    OT_QUAD,
91
};
92

    
93
enum {
94
    /* I386 int registers */
95
    OR_EAX,   /* MUST be even numbered */
96
    OR_ECX,
97
    OR_EDX,
98
    OR_EBX,
99
    OR_ESP,
100
    OR_EBP,
101
    OR_ESI,
102
    OR_EDI,
103

    
104
    /* I386 float registers */
105
    OR_ST0,
106
    OR_ST1,
107
    OR_ST2,
108
    OR_ST3,
109
    OR_ST4,
110
    OR_ST5,
111
    OR_ST6,
112
    OR_ST7,
113
    OR_TMP0,    /* temporary operand register */
114
    OR_TMP1,
115
    OR_A0, /* temporary register used when doing address evaluation */
116
    OR_EFLAGS,  /* cpu flags */
117
    OR_ITMP0, /* used for byte/word insertion */
118
    OR_ITMP1, /* used for byte/word insertion */
119
    OR_ITMP2, /* used for byte/word insertion */
120
    OR_FTMP0, /* float temporary */
121
    OR_DF,    /* D flag, for string ops */
122
    OR_ZERO, /* fixed zero register */
123
    OR_IM, /* dummy immediate value register */
124
    NB_OREGS,
125
};
126

    
127
#if 0
128
static const double tab_const[7] = {
129
    1.0, 
130
    3.32192809488736234789, /* log2(10) */
131
    M_LOG2E,
132
    M_PI,
133
    0.30102999566398119521, /* log10(2) */
134
    M_LN2,
135
    0.0
136
};
137
#endif
138

    
139
typedef void (GenOpFunc)(void);
140
typedef void (GenOpFunc1)(long);
141
typedef void (GenOpFunc2)(long, long);
142
                    
143
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
144
    [OT_BYTE] = {
145
        gen_op_movb_EAX_T0,
146
        gen_op_movb_ECX_T0,
147
        gen_op_movb_EDX_T0,
148
        gen_op_movb_EBX_T0,
149
        gen_op_movh_EAX_T0,
150
        gen_op_movh_ECX_T0,
151
        gen_op_movh_EDX_T0,
152
        gen_op_movh_EBX_T0,
153
    },
154
    [OT_WORD] = {
155
        gen_op_movw_EAX_T0,
156
        gen_op_movw_ECX_T0,
157
        gen_op_movw_EDX_T0,
158
        gen_op_movw_EBX_T0,
159
        gen_op_movw_ESP_T0,
160
        gen_op_movw_EBP_T0,
161
        gen_op_movw_ESI_T0,
162
        gen_op_movw_EDI_T0,
163
    },
164
    [OT_LONG] = {
165
        gen_op_movl_EAX_T0,
166
        gen_op_movl_ECX_T0,
167
        gen_op_movl_EDX_T0,
168
        gen_op_movl_EBX_T0,
169
        gen_op_movl_ESP_T0,
170
        gen_op_movl_EBP_T0,
171
        gen_op_movl_ESI_T0,
172
        gen_op_movl_EDI_T0,
173
    },
174
};
175

    
176
static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
177
    [OT_BYTE] = {
178
        gen_op_movb_EAX_T1,
179
        gen_op_movb_ECX_T1,
180
        gen_op_movb_EDX_T1,
181
        gen_op_movb_EBX_T1,
182
        gen_op_movh_EAX_T1,
183
        gen_op_movh_ECX_T1,
184
        gen_op_movh_EDX_T1,
185
        gen_op_movh_EBX_T1,
186
    },
187
    [OT_WORD] = {
188
        gen_op_movw_EAX_T1,
189
        gen_op_movw_ECX_T1,
190
        gen_op_movw_EDX_T1,
191
        gen_op_movw_EBX_T1,
192
        gen_op_movw_ESP_T1,
193
        gen_op_movw_EBP_T1,
194
        gen_op_movw_ESI_T1,
195
        gen_op_movw_EDI_T1,
196
    },
197
    [OT_LONG] = {
198
        gen_op_movl_EAX_T1,
199
        gen_op_movl_ECX_T1,
200
        gen_op_movl_EDX_T1,
201
        gen_op_movl_EBX_T1,
202
        gen_op_movl_ESP_T1,
203
        gen_op_movl_EBP_T1,
204
        gen_op_movl_ESI_T1,
205
        gen_op_movl_EDI_T1,
206
    },
207
};
208

    
209
static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
210
    [0] = {
211
        gen_op_movw_EAX_A0,
212
        gen_op_movw_ECX_A0,
213
        gen_op_movw_EDX_A0,
214
        gen_op_movw_EBX_A0,
215
        gen_op_movw_ESP_A0,
216
        gen_op_movw_EBP_A0,
217
        gen_op_movw_ESI_A0,
218
        gen_op_movw_EDI_A0,
219
    },
220
    [1] = {
221
        gen_op_movl_EAX_A0,
222
        gen_op_movl_ECX_A0,
223
        gen_op_movl_EDX_A0,
224
        gen_op_movl_EBX_A0,
225
        gen_op_movl_ESP_A0,
226
        gen_op_movl_EBP_A0,
227
        gen_op_movl_ESI_A0,
228
        gen_op_movl_EDI_A0,
229
    },
230
};
231

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

    
302
static GenOpFunc *gen_op_movl_A0_reg[8] = {
303
    gen_op_movl_A0_EAX,
304
    gen_op_movl_A0_ECX,
305
    gen_op_movl_A0_EDX,
306
    gen_op_movl_A0_EBX,
307
    gen_op_movl_A0_ESP,
308
    gen_op_movl_A0_EBP,
309
    gen_op_movl_A0_ESI,
310
    gen_op_movl_A0_EDI,
311
};
312

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

    
356
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
357
    gen_op_addl_T0_T1_cc,
358
    gen_op_orl_T0_T1_cc,
359
    gen_op_adcl_T0_T1_cc,
360
    gen_op_sbbl_T0_T1_cc,
361
    gen_op_andl_T0_T1_cc,
362
    gen_op_subl_T0_T1_cc,
363
    gen_op_xorl_T0_T1_cc,
364
    gen_op_cmpl_T0_T1_cc,
365
};
366

    
367
static const int cc_op_arithb[8] = {
368
    CC_OP_ADDB,
369
    CC_OP_LOGICB,
370
    CC_OP_ADDB,
371
    CC_OP_SUBB,
372
    CC_OP_LOGICB,
373
    CC_OP_SUBB,
374
    CC_OP_LOGICB,
375
    CC_OP_SUBB,
376
};
377

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

    
411
static GenOpFunc *gen_op_lds_T0_A0[3] = {
412
    gen_op_ldsb_T0_A0,
413
    gen_op_ldsw_T0_A0,
414
};
415

    
416
static GenOpFunc *gen_op_ldu_T0_A0[3] = {
417
    gen_op_ldub_T0_A0,
418
    gen_op_lduw_T0_A0,
419
};
420

    
421
/* sign does not matter */
422
static GenOpFunc *gen_op_ld_T0_A0[3] = {
423
    gen_op_ldub_T0_A0,
424
    gen_op_lduw_T0_A0,
425
    gen_op_ldl_T0_A0,
426
};
427

    
428
static GenOpFunc *gen_op_ld_T1_A0[3] = {
429
    gen_op_ldub_T1_A0,
430
    gen_op_lduw_T1_A0,
431
    gen_op_ldl_T1_A0,
432
};
433

    
434
static GenOpFunc *gen_op_st_T0_A0[3] = {
435
    gen_op_stb_T0_A0,
436
    gen_op_stw_T0_A0,
437
    gen_op_stl_T0_A0,
438
};
439

    
440
static GenOpFunc *gen_op_movs[6] = {
441
    gen_op_movsb,
442
    gen_op_movsw,
443
    gen_op_movsl,
444
    gen_op_rep_movsb,
445
    gen_op_rep_movsw,
446
    gen_op_rep_movsl,
447
};
448

    
449
static GenOpFunc *gen_op_stos[6] = {
450
    gen_op_stosb,
451
    gen_op_stosw,
452
    gen_op_stosl,
453
    gen_op_rep_stosb,
454
    gen_op_rep_stosw,
455
    gen_op_rep_stosl,
456
};
457

    
458
static GenOpFunc *gen_op_lods[6] = {
459
    gen_op_lodsb,
460
    gen_op_lodsw,
461
    gen_op_lodsl,
462
    gen_op_rep_lodsb,
463
    gen_op_rep_lodsw,
464
    gen_op_rep_lodsl,
465
};
466

    
467
static GenOpFunc *gen_op_scas[9] = {
468
    gen_op_scasb,
469
    gen_op_scasw,
470
    gen_op_scasl,
471
    gen_op_repz_scasb,
472
    gen_op_repz_scasw,
473
    gen_op_repz_scasl,
474
    gen_op_repnz_scasb,
475
    gen_op_repnz_scasw,
476
    gen_op_repnz_scasl,
477
};
478

    
479
static GenOpFunc *gen_op_cmps[9] = {
480
    gen_op_cmpsb,
481
    gen_op_cmpsw,
482
    gen_op_cmpsl,
483
    gen_op_repz_cmpsb,
484
    gen_op_repz_cmpsw,
485
    gen_op_repz_cmpsl,
486
    gen_op_repnz_cmpsb,
487
    gen_op_repnz_cmpsw,
488
    gen_op_repnz_cmpsl,
489
};
490

    
491
static GenOpFunc *gen_op_ins[6] = {
492
    gen_op_insb,
493
    gen_op_insw,
494
    gen_op_insl,
495
    gen_op_rep_insb,
496
    gen_op_rep_insw,
497
    gen_op_rep_insl,
498
};
499

    
500

    
501
static GenOpFunc *gen_op_outs[6] = {
502
    gen_op_outsb,
503
    gen_op_outsw,
504
    gen_op_outsl,
505
    gen_op_rep_outsb,
506
    gen_op_rep_outsw,
507
    gen_op_rep_outsl,
508
};
509

    
510
enum {
511
    JCC_O,
512
    JCC_B,
513
    JCC_Z,
514
    JCC_BE,
515
    JCC_S,
516
    JCC_P,
517
    JCC_L,
518
    JCC_LE,
519
};
520

    
521
static GenOpFunc2 *gen_jcc_slow[8] = {
522
    gen_op_jo_cc,
523
    gen_op_jb_cc,
524
    gen_op_jz_cc,
525
    gen_op_jbe_cc,
526
    gen_op_js_cc,
527
    gen_op_jp_cc,
528
    gen_op_jl_cc,
529
    gen_op_jle_cc,
530
};
531
    
532
static GenOpFunc2 *gen_jcc_sub[3][8] = {
533
    [OT_BYTE] = {
534
        NULL,
535
        gen_op_jb_subb,
536
        gen_op_jz_subb,
537
        gen_op_jbe_subb,
538
        gen_op_js_subb,
539
        NULL,
540
        gen_op_jl_subb,
541
        gen_op_jle_subb,
542
    },
543
    [OT_WORD] = {
544
        NULL,
545
        gen_op_jb_subw,
546
        gen_op_jz_subw,
547
        gen_op_jbe_subw,
548
        gen_op_js_subw,
549
        NULL,
550
        gen_op_jl_subw,
551
        gen_op_jle_subw,
552
    },
553
    [OT_LONG] = {
554
        NULL,
555
        gen_op_jb_subl,
556
        gen_op_jz_subl,
557
        gen_op_jbe_subl,
558
        gen_op_js_subl,
559
        NULL,
560
        gen_op_jl_subl,
561
        gen_op_jle_subl,
562
    },
563
};
564

    
565
static GenOpFunc *gen_setcc_slow[8] = {
566
    gen_op_seto_T0_cc,
567
    gen_op_setb_T0_cc,
568
    gen_op_setz_T0_cc,
569
    gen_op_setbe_T0_cc,
570
    gen_op_sets_T0_cc,
571
    gen_op_setp_T0_cc,
572
    gen_op_setl_T0_cc,
573
    gen_op_setle_T0_cc,
574
};
575

    
576
static GenOpFunc *gen_setcc_sub[3][8] = {
577
    [OT_BYTE] = {
578
        NULL,
579
        gen_op_setb_T0_subb,
580
        gen_op_setz_T0_subb,
581
        gen_op_setbe_T0_subb,
582
        gen_op_sets_T0_subb,
583
        NULL,
584
        gen_op_setl_T0_subb,
585
        gen_op_setle_T0_subb,
586
    },
587
    [OT_WORD] = {
588
        NULL,
589
        gen_op_setb_T0_subw,
590
        gen_op_setz_T0_subw,
591
        gen_op_setbe_T0_subw,
592
        gen_op_sets_T0_subw,
593
        NULL,
594
        gen_op_setl_T0_subw,
595
        gen_op_setle_T0_subw,
596
    },
597
    [OT_LONG] = {
598
        NULL,
599
        gen_op_setb_T0_subl,
600
        gen_op_setz_T0_subl,
601
        gen_op_setbe_T0_subl,
602
        gen_op_sets_T0_subl,
603
        NULL,
604
        gen_op_setl_T0_subl,
605
        gen_op_setle_T0_subl,
606
    },
607
};
608

    
609
static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
610
{
611
    if (d != OR_TMP0)
612
        gen_op_mov_TN_reg[ot][0][d]();
613
    if (s != OR_TMP1)
614
        gen_op_mov_TN_reg[ot][1][s]();
615
    if ((op == OP_ADCL || op == OP_SBBL) && s1->cc_op != CC_OP_DYNAMIC)
616
        gen_op_set_cc_op(s1->cc_op);
617
    gen_op_arith_T0_T1_cc[op]();
618
    if (d != OR_TMP0 && op != OP_CMPL)
619
        gen_op_mov_reg_T0[ot][d]();
620
    s1->cc_op = cc_op_arithb[op] + ot;
621
}
622

    
623
static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
624
{
625
    gen_op1_movl_T1_im(c);
626
    gen_op(s1, op, ot, d, OR_TMP0);
627
}
628

    
629
static void gen_inc(DisasContext *s1, int ot, int d, int c)
630
{
631
    if (d != OR_TMP0)
632
        gen_op_mov_TN_reg[ot][0][d]();
633
    if (s1->cc_op != CC_OP_DYNAMIC)
634
        gen_op_set_cc_op(s1->cc_op);
635
    if (c > 0)
636
        gen_op_incl_T0_cc();
637
    else
638
        gen_op_decl_T0_cc();
639
    if (d != OR_TMP0)
640
        gen_op_mov_reg_T0[ot][d]();
641
}
642

    
643
static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
644
{
645
    if (d != OR_TMP0)
646
        gen_op_mov_TN_reg[ot][0][d]();
647
    if (s != OR_TMP1)
648
        gen_op_mov_TN_reg[ot][1][s]();
649
    switch(op) {
650
    case OP_ROL:
651
    case OP_ROR:
652
    case OP_RCL:
653
    case OP_RCR:
654
        /* only C and O are modified, so we must update flags dynamically */
655
        if (s1->cc_op != CC_OP_DYNAMIC)
656
            gen_op_set_cc_op(s1->cc_op);
657
        gen_op_shift_T0_T1_cc[ot][op]();
658
        break;
659
    default:
660
        gen_op_shift_T0_T1_cc[ot][op]();
661
        break;
662
    }
663
    if (d != OR_TMP0)
664
        gen_op_mov_reg_T0[ot][d]();
665
    s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
666
}
667

    
668
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
669
{
670
    /* currently not optimized */
671
    gen_op1_movl_T1_im(c);
672
    gen_shift(s1, op, ot, d, OR_TMP1);
673
}
674

    
675
static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
676
{
677
    int havesib;
678
    int havebase;
679
    int base, disp;
680
    int index = 0;
681
    int scale = 0;
682
    int reg1, reg2, opreg;
683
    int mod, rm, code;
684

    
685
    mod = (modrm >> 6) & 3;
686
    rm = modrm & 7;
687

    
688
    if (s->aflag) {
689

    
690
        havesib = 0;
691
        havebase = 1;
692
        base = rm;
693
        
694
        if (base == 4) {
695
            havesib = 1;
696
            code = ldub(s->pc++);
697
            scale = (code >> 6) & 3;
698
            index = (code >> 3) & 7;
699
            base = code & 7;
700
        }
701

    
702
        switch (mod) {
703
        case 0:
704
            if (base == 5) {
705
                havebase = 0;
706
                disp = ldl(s->pc);
707
                s->pc += 4;
708
            } else {
709
                disp = 0;
710
            }
711
            break;
712
        case 1:
713
            disp = (int8_t)ldub(s->pc++);
714
            break;
715
        default:
716
        case 2:
717
            disp = ldl(s->pc);
718
            s->pc += 4;
719
            break;
720
        }
721

    
722
        reg1 = OR_ZERO;
723
        reg2 = OR_ZERO;
724
          
725
        if (havebase || (havesib && (index != 4 || scale != 0))) {
726
            if (havebase)
727
                reg1 = OR_EAX + base;
728
            if (havesib && index != 4) {
729
                if (havebase)
730
                    reg2 = index + OR_EAX;
731
                else
732
                    reg1 = index + OR_EAX;
733
            }
734
        }
735
        /* XXX: disp only ? */
736
        if (reg2 == OR_ZERO) {
737
            /* op: disp + (reg1 << scale) */
738
            if (reg1 == OR_ZERO) {
739
                gen_op1_movl_A0_im(disp);
740
            } else if (scale == 0 && disp == 0) {
741
                gen_op_movl_A0_reg[reg1]();
742
            } else {
743
                gen_op_addl_A0_reg_sN[scale][reg1]();
744
            }
745
        } else {
746
            /* op: disp + reg1 + (reg2 << scale) */
747
            if (disp != 0) {
748
                gen_op1_movl_A0_im(disp);
749
                gen_op_addl_A0_reg_sN[0][reg1]();
750
            } else {
751
                gen_op_movl_A0_reg[reg1]();
752
            }
753
            gen_op_addl_A0_reg_sN[scale][reg2]();
754
        }
755
        opreg = OR_A0;
756
    } else {
757
        fprintf(stderr, "16 bit addressing not supported\n");
758
        disp = 0;
759
        opreg = 0;
760
    }
761
    *reg_ptr = opreg;
762
    *offset_ptr = disp;
763
}
764

    
765
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
766
   OR_TMP0 */
767
static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
768
{
769
    int mod, rm, opreg, disp;
770

    
771
    mod = (modrm >> 6) & 3;
772
    rm = modrm & 7;
773
    if (mod == 3) {
774
        if (is_store) {
775
            if (reg != OR_TMP0)
776
                gen_op_mov_TN_reg[ot][0][reg]();
777
            gen_op_mov_reg_T0[ot][rm]();
778
        } else {
779
            gen_op_mov_TN_reg[ot][0][rm]();
780
            if (reg != OR_TMP0)
781
                gen_op_mov_reg_T0[ot][reg]();
782
        }
783
    } else {
784
        gen_lea_modrm(s, modrm, &opreg, &disp);
785
        if (is_store) {
786
            if (reg != OR_TMP0)
787
                gen_op_mov_TN_reg[ot][0][reg]();
788
            gen_op_st_T0_A0[ot]();
789
        } else {
790
            gen_op_ld_T0_A0[ot]();
791
            if (reg != OR_TMP0)
792
                gen_op_mov_reg_T0[ot][reg]();
793
        }
794
    }
795
}
796

    
797
static inline uint32_t insn_get(DisasContext *s, int ot)
798
{
799
    uint32_t ret;
800

    
801
    switch(ot) {
802
    case OT_BYTE:
803
        ret = ldub(s->pc);
804
        s->pc++;
805
        break;
806
    case OT_WORD:
807
        ret = lduw(s->pc);
808
        s->pc += 2;
809
        break;
810
    default:
811
    case OT_LONG:
812
        ret = ldl(s->pc);
813
        s->pc += 4;
814
        break;
815
    }
816
    return ret;
817
}
818

    
819
static void gen_jcc(DisasContext *s, int b, int val)
820
{
821
    int inv, jcc_op;
822
    GenOpFunc2 *func;
823

    
824
    inv = b & 1;
825
    jcc_op = (b >> 1) & 7;
826
    switch(s->cc_op) {
827
        /* we optimize the cmp/jcc case */
828
    case CC_OP_SUBB:
829
    case CC_OP_SUBW:
830
    case CC_OP_SUBL:
831
        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
832
        if (!func)
833
            goto slow_jcc;
834
        break;
835
        
836
        /* some jumps are easy to compute */
837
    case CC_OP_ADDB:
838
    case CC_OP_ADDW:
839
    case CC_OP_ADDL:
840
    case CC_OP_LOGICB:
841
    case CC_OP_LOGICW:
842
    case CC_OP_LOGICL:
843
    case CC_OP_INCB:
844
    case CC_OP_INCW:
845
    case CC_OP_INCL:
846
    case CC_OP_DECB:
847
    case CC_OP_DECW:
848
    case CC_OP_DECL:
849
    case CC_OP_SHLB:
850
    case CC_OP_SHLW:
851
    case CC_OP_SHLL:
852
        switch(jcc_op) {
853
        case JCC_Z:
854
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
855
            break;
856
        case JCC_S:
857
            func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
858
            break;
859
        default:
860
            goto slow_jcc;
861
        }
862
        break;
863
    default:
864
    slow_jcc:
865
        if (s->cc_op != CC_OP_DYNAMIC)
866
            op_set_cc_op(s->cc_op);
867
        func = gen_jcc_slow[jcc_op];
868
        break;
869
    }
870
    if (!inv) {
871
        func(val, (long)s->pc);
872
    } else {
873
        func((long)s->pc, val);
874
    }
875
}
876

    
877
static void gen_setcc(DisasContext *s, int b)
878
{
879
    int inv, jcc_op;
880
    GenOpFunc *func;
881

    
882
    inv = b & 1;
883
    jcc_op = (b >> 1) & 7;
884
    switch(s->cc_op) {
885
        /* we optimize the cmp/jcc case */
886
    case CC_OP_SUBB:
887
    case CC_OP_SUBW:
888
    case CC_OP_SUBL:
889
        func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
890
        if (!func)
891
            goto slow_jcc;
892
        break;
893
        
894
        /* some jumps are easy to compute */
895
    case CC_OP_ADDB:
896
    case CC_OP_ADDW:
897
    case CC_OP_ADDL:
898
    case CC_OP_LOGICB:
899
    case CC_OP_LOGICW:
900
    case CC_OP_LOGICL:
901
    case CC_OP_INCB:
902
    case CC_OP_INCW:
903
    case CC_OP_INCL:
904
    case CC_OP_DECB:
905
    case CC_OP_DECW:
906
    case CC_OP_DECL:
907
    case CC_OP_SHLB:
908
    case CC_OP_SHLW:
909
    case CC_OP_SHLL:
910
        switch(jcc_op) {
911
        case JCC_Z:
912
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
913
            break;
914
        case JCC_S:
915
            func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
916
            break;
917
        default:
918
            goto slow_jcc;
919
        }
920
        break;
921
    default:
922
    slow_jcc:
923
        if (s->cc_op != CC_OP_DYNAMIC)
924
            op_set_cc_op(s->cc_op);
925
        func = gen_setcc_slow[jcc_op];
926
        break;
927
    }
928
    func();
929
    if (inv) {
930
        gen_op_xor_T0_1();
931
    }
932
}
933

    
934
/* return the size of the intruction. Return -1 if no insn found */
935
int disas_insn(DisasContext *s, uint8_t *pc_start)
936
{
937
    int b, prefixes, aflag, dflag;
938
    int shift, ot;
939
    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
940

    
941
    s->pc = pc_start;
942
    prefixes = 0;
943
    aflag = 1;
944
    dflag = 1;
945
    //    cur_pc = s->pc; /* for insn generation */
946
 next_byte:
947
    b = ldub(s->pc);
948
    if (b < 0)
949
        return -1;
950
    s->pc++;
951
    /* check prefixes */
952
    switch (b) {
953
    case 0xf3:
954
        prefixes |= PREFIX_REPZ;
955
        goto next_byte;
956
    case 0xf2:
957
        prefixes |= PREFIX_REPNZ;
958
        goto next_byte;
959
    case 0xf0:
960
        prefixes |= PREFIX_LOCK;
961
        goto next_byte;
962
    case 0x2e:
963
        prefixes |= PREFIX_CS;
964
        goto next_byte;
965
    case 0x36:
966
        prefixes |= PREFIX_SS;
967
        goto next_byte;
968
    case 0x3e:
969
        prefixes |= PREFIX_DS;
970
        goto next_byte;
971
    case 0x26:
972
        prefixes |= PREFIX_ES;
973
        goto next_byte;
974
    case 0x64:
975
        prefixes |= PREFIX_FS;
976
        goto next_byte;
977
    case 0x65:
978
        prefixes |= PREFIX_GS;
979
        goto next_byte;
980
    case 0x66:
981
        prefixes |= PREFIX_DATA;
982
        goto next_byte;
983
    case 0x67:
984
        prefixes |= PREFIX_ADR;
985
        goto next_byte;
986
    case 0x9b:
987
        prefixes |= PREFIX_FWAIT;
988
        goto next_byte;
989
    }
990

    
991
    if (prefixes & PREFIX_DATA)
992
        dflag ^= 1;
993
    if (prefixes & PREFIX_ADR)
994
        aflag ^= 1;
995

    
996
    s->prefix = prefixes;
997
    s->aflag = aflag;
998
    s->dflag = dflag;
999

    
1000
    /* now check op code */
1001
 reswitch:
1002
    switch(b) {
1003
    case 0x0f:
1004
        /**************************/
1005
        /* extended op code */
1006
        b = ldub(s->pc++) | 0x100;
1007
        goto reswitch;
1008
        
1009
        /**************************/
1010
        /* arith & logic */
1011
    case 0x00 ... 0x05:
1012
    case 0x08 ... 0x0d:
1013
    case 0x10 ... 0x15:
1014
    case 0x18 ... 0x1d:
1015
    case 0x20 ... 0x25:
1016
    case 0x28 ... 0x2d:
1017
    case 0x30 ... 0x35:
1018
    case 0x38 ... 0x3d:
1019
        {
1020
            int op, f, val;
1021
            op = (b >> 3) & 7;
1022
            f = (b >> 1) & 3;
1023

    
1024
            if ((b & 1) == 0)
1025
                ot = OT_BYTE;
1026
            else
1027
                ot = dflag ? OT_LONG : OT_WORD;
1028
            
1029
            switch(f) {
1030
            case 0: /* OP Ev, Gv */
1031
                modrm = ldub(s->pc++);
1032
                reg = ((modrm >> 3) & 7) + OR_EAX;
1033
                mod = (modrm >> 6) & 3;
1034
                rm = modrm & 7;
1035
                if (mod != 3) {
1036
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1037
                    gen_op_ld_T0_A0[ot]();
1038
                    opreg = OR_TMP0;
1039
                } else {
1040
                    opreg = OR_EAX + rm;
1041
                }
1042
                gen_op(s, op, ot, opreg, reg);
1043
                if (mod != 3 && op != 7) {
1044
                    gen_op_st_T0_A0[ot]();
1045
                }
1046
                break;
1047
            case 1: /* OP Gv, Ev */
1048
                modrm = ldub(s->pc++);
1049
                mod = (modrm >> 6) & 3;
1050
                reg = ((modrm >> 3) & 7) + OR_EAX;
1051
                rm = modrm & 7;
1052
                if (mod != 3) {
1053
                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1054
                    gen_op_ld_T1_A0[ot]();
1055
                    opreg = OR_TMP1;
1056
                } else {
1057
                    opreg = OR_EAX + rm;
1058
                }
1059
                gen_op(s, op, ot, reg, opreg);
1060
                break;
1061
            case 2: /* OP A, Iv */
1062
                val = insn_get(s, ot);
1063
                gen_opi(s, op, ot, OR_EAX, val);
1064
                break;
1065
            }
1066
        }
1067
        break;
1068

    
1069
    case 0x80: /* GRP1 */
1070
    case 0x81:
1071
    case 0x83:
1072
        {
1073
            int val;
1074

    
1075
            if ((b & 1) == 0)
1076
                ot = OT_BYTE;
1077
            else
1078
                ot = dflag ? OT_LONG : OT_WORD;
1079
            
1080
            modrm = ldub(s->pc++);
1081
            mod = (modrm >> 6) & 3;
1082
            rm = modrm & 7;
1083
            op = (modrm >> 3) & 7;
1084
            
1085
            if (mod != 3) {
1086
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1087
                gen_op_ld_T0_A0[ot]();
1088
                opreg = OR_TMP0;
1089
            } else {
1090
                opreg = rm + OR_EAX;
1091
            }
1092

    
1093
            switch(b) {
1094
            default:
1095
            case 0x80:
1096
            case 0x81:
1097
                val = insn_get(s, ot);
1098
                break;
1099
            case 0x83:
1100
                val = (int8_t)insn_get(s, OT_BYTE);
1101
                break;
1102
            }
1103

    
1104
            gen_opi(s, op, ot, opreg, val);
1105
            if (op != 7 && mod != 3) {
1106
                gen_op_st_T0_A0[ot]();
1107
            }
1108
        }
1109
        break;
1110

    
1111
        /**************************/
1112
        /* inc, dec, and other misc arith */
1113
    case 0x40 ... 0x47: /* inc Gv */
1114
        ot = dflag ? OT_LONG : OT_WORD;
1115
        gen_inc(s, ot, OR_EAX + (b & 7), 1);
1116
        break;
1117
    case 0x48 ... 0x4f: /* dec Gv */
1118
        ot = dflag ? OT_LONG : OT_WORD;
1119
        gen_inc(s, ot, OR_EAX + (b & 7), -1);
1120
        break;
1121
    case 0xf6: /* GRP3 */
1122
    case 0xf7:
1123
        if ((b & 1) == 0)
1124
            ot = OT_BYTE;
1125
        else
1126
            ot = dflag ? OT_LONG : OT_WORD;
1127

    
1128
        modrm = ldub(s->pc++);
1129
        mod = (modrm >> 6) & 3;
1130
        rm = modrm & 7;
1131
        op = (modrm >> 3) & 7;
1132
        if (mod != 3) {
1133
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1134
            gen_op_ld_T0_A0[ot]();
1135
        } else {
1136
            gen_op_mov_TN_reg[ot][0][rm]();
1137
        }
1138

    
1139
        switch(op) {
1140
        case 0: /* test */
1141
            val = insn_get(s, ot);
1142
            gen_op1_movl_T1_im(val);
1143
            gen_op_testl_T0_T1_cc();
1144
            s->cc_op = CC_OP_LOGICB + ot;
1145
            break;
1146
        case 2: /* not */
1147
            gen_op_notl_T0();
1148
            if (mod != 3) {
1149
                gen_op_st_T0_A0[ot]();
1150
            } else {
1151
                gen_op_mov_reg_T0[ot][rm]();
1152
            }
1153
            break;
1154
        case 3: /* neg */
1155
            gen_op_negl_T0_cc();
1156
            if (mod != 3) {
1157
                gen_op_st_T0_A0[ot]();
1158
            } else {
1159
                gen_op_mov_reg_T0[ot][rm]();
1160
            }
1161
            s->cc_op = CC_OP_SUBB + ot;
1162
            break;
1163
        case 4: /* mul */
1164
            switch(ot) {
1165
            case OT_BYTE:
1166
                gen_op_mulb_AL_T0();
1167
                break;
1168
            case OT_WORD:
1169
                gen_op_mulw_AX_T0();
1170
                break;
1171
            default:
1172
            case OT_LONG:
1173
                gen_op_mull_EAX_T0();
1174
                break;
1175
            }
1176
            break;
1177
        case 5: /* imul */
1178
            switch(ot) {
1179
            case OT_BYTE:
1180
                gen_op_imulb_AL_T0();
1181
                break;
1182
            case OT_WORD:
1183
                gen_op_imulw_AX_T0();
1184
                break;
1185
            default:
1186
            case OT_LONG:
1187
                gen_op_imull_EAX_T0();
1188
                break;
1189
            }
1190
            break;
1191
        case 6: /* div */
1192
            switch(ot) {
1193
            case OT_BYTE:
1194
                gen_op_divb_AL_T0();
1195
                break;
1196
            case OT_WORD:
1197
                gen_op_divw_AX_T0();
1198
                break;
1199
            default:
1200
            case OT_LONG:
1201
                gen_op_divl_EAX_T0();
1202
                break;
1203
            }
1204
            break;
1205
        case 7: /* idiv */
1206
            switch(ot) {
1207
            case OT_BYTE:
1208
                gen_op_idivb_AL_T0();
1209
                break;
1210
            case OT_WORD:
1211
                gen_op_idivw_AX_T0();
1212
                break;
1213
            default:
1214
            case OT_LONG:
1215
                gen_op_idivl_EAX_T0();
1216
                break;
1217
            }
1218
            break;
1219
        default:
1220
            error("GRP3: bad instruction");
1221
            return -1;
1222
        }
1223
        break;
1224

    
1225
    case 0xfe: /* GRP4 */
1226
    case 0xff: /* GRP5 */
1227
        if ((b & 1) == 0)
1228
            ot = OT_BYTE;
1229
        else
1230
            ot = dflag ? OT_LONG : OT_WORD;
1231

    
1232
        modrm = ldub(s->pc++);
1233
        mod = (modrm >> 6) & 3;
1234
        rm = modrm & 7;
1235
        op = (modrm >> 3) & 7;
1236
        if (op >= 2 && b == 0xfe) {
1237
            error("GRP4: bad instruction");
1238
            return -1;
1239
        }
1240
        if (mod != 3) {
1241
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1242
            gen_op_ld_T0_A0[ot]();
1243
        } else {
1244
            gen_op_mov_TN_reg[ot][0][rm]();
1245
        }
1246

    
1247
        switch(op) {
1248
        case 0: /* inc Ev */
1249
            gen_inc(s, ot, OR_TMP0, 1);
1250
            if (mod != 3)
1251
                gen_op_st_T0_A0[ot]();
1252
            break;
1253
        case 1: /* dec Ev */
1254
            gen_inc(s, ot, OR_TMP0, -1);
1255
            if (mod != 3)
1256
                gen_op_st_T0_A0[ot]();
1257
            break;
1258
        case 2: /* call Ev */
1259
            gen_op1_movl_T1_im((long)s->pc);
1260
            gen_op_pushl_T1();
1261
            gen_op_jmp_T0();
1262
            break;
1263
        case 4: /* jmp Ev */
1264
            gen_op_jmp_T0();
1265
            break;
1266
        case 6: /* push Ev */
1267
            gen_op_pushl_T0();
1268
            break;
1269
        default:
1270
            error("GRP5: bad instruction");
1271
            return -1;
1272
        }
1273
        break;
1274

    
1275
    case 0x84: /* test Ev, Gv */
1276
    case 0x85: 
1277
        if ((b & 1) == 0)
1278
            ot = OT_BYTE;
1279
        else
1280
            ot = dflag ? OT_LONG : OT_WORD;
1281

    
1282
        modrm = ldub(s->pc++);
1283
        mod = (modrm >> 6) & 3;
1284
        rm = modrm & 7;
1285
        reg = (modrm >> 3) & 7;
1286
        
1287
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1288
        gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1289
        gen_op_testl_T0_T1_cc();
1290
        s->cc_op = CC_OP_LOGICB + ot;
1291
        break;
1292
        
1293
    case 0xa8: /* test eAX, Iv */
1294
    case 0xa9:
1295
        if ((b & 1) == 0)
1296
            ot = OT_BYTE;
1297
        else
1298
            ot = dflag ? OT_LONG : OT_WORD;
1299
        val = insn_get(s, ot);
1300

    
1301
        gen_op_mov_TN_reg[ot][0][OR_EAX]();
1302
        gen_op1_movl_T1_im(val);
1303
        gen_op_testl_T0_T1_cc();
1304
        s->cc_op = CC_OP_LOGICB + ot;
1305
        break;
1306
        
1307
    case 0x98: /* CWDE/CBW */
1308
        if (dflag)
1309
            gen_op_movswl_EAX_AX();
1310
        else
1311
            gen_op_movsbw_AX_AL();
1312
        break;
1313
    case 0x99: /* CDQ/CWD */
1314
        if (dflag)
1315
            gen_op_movslq_EDX_EAX();
1316
        else
1317
            gen_op_movswl_DX_AX();
1318
        break;
1319
    case 0x1af: /* imul Gv, Ev */
1320
    case 0x69: /* imul Gv, Ev, I */
1321
    case 0x6b:
1322
        ot = dflag ? OT_LONG : OT_WORD;
1323
        modrm = ldub(s->pc++);
1324
        reg = ((modrm >> 3) & 7) + OR_EAX;
1325
        
1326
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1327
        if (b == 0x69) {
1328
            val = insn_get(s, ot);
1329
            gen_op1_movl_T1_im(val);
1330
        } else if (b == 0x6b) {
1331
            val = insn_get(s, OT_BYTE);
1332
            gen_op1_movl_T1_im(val);
1333
        } else {
1334
            gen_op_mov_TN_reg[ot][1][reg]();
1335
        }
1336

    
1337
        if (ot == OT_LONG) {
1338
            op_imull_T0_T1();
1339
        } else {
1340
            op_imulw_T0_T1();
1341
        }
1342
        gen_op_mov_reg_T0[ot][reg]();
1343
        break;
1344
        
1345
        /**************************/
1346
        /* push/pop */
1347
    case 0x50 ... 0x57: /* push */
1348
        gen_op_mov_TN_reg[OT_LONG][0][(b & 7)]();
1349
        gen_op_pushl_T0();
1350
        break;
1351
    case 0x58 ... 0x5f: /* pop */
1352
        gen_op_popl_T0();
1353
        gen_op_mov_reg_T0[OT_LONG][reg]();
1354
        break;
1355
    case 0x68: /* push Iv */
1356
    case 0x6a:
1357
        ot = dflag ? OT_LONG : OT_WORD;
1358
        if (b == 0x68)
1359
            val = insn_get(s, ot);
1360
        else
1361
            val = (int8_t)insn_get(s, OT_BYTE);
1362
        gen_op1_movl_T0_im(val);
1363
        gen_op_pushl_T0();
1364
        break;
1365
    case 0x8f: /* pop Ev */
1366
        ot = dflag ? OT_LONG : OT_WORD;
1367
        modrm = ldub(s->pc++);
1368
        gen_op_popl_T0();
1369
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1370
        break;
1371
    case 0xc9: /* leave */
1372
        gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1373
        gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1374
        gen_op_popl_T0();
1375
        gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1376
        break;
1377
        /**************************/
1378
        /* mov */
1379
    case 0x88:
1380
    case 0x89: /* mov Gv, Ev */
1381
        if ((b & 1) == 0)
1382
            ot = OT_BYTE;
1383
        else
1384
            ot = dflag ? OT_LONG : OT_WORD;
1385
        modrm = ldub(s->pc++);
1386
        reg = (modrm >> 3) & 7;
1387
        
1388
        /* generate a generic store */
1389
        gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1390
        break;
1391
    case 0xc6:
1392
    case 0xc7: /* mov Ev, Iv */
1393
        if ((b & 1) == 0)
1394
            ot = OT_BYTE;
1395
        else
1396
            ot = dflag ? OT_LONG : OT_WORD;
1397
        modrm = ldub(s->pc++);
1398
        mod = (modrm >> 6) & 3;
1399

    
1400
        val = insn_get(s, ot);
1401
        gen_op1_movl_T0_im(val);
1402
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1403
        break;
1404
    case 0x8a:
1405
    case 0x8b: /* mov Ev, Gv */
1406
        if ((b & 1) == 0)
1407
            ot = OT_BYTE;
1408
        else
1409
            ot = dflag ? OT_LONG : OT_WORD;
1410
        modrm = ldub(s->pc++);
1411
        reg = (modrm >> 3) & 7;
1412
        
1413
        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1414
        gen_op_mov_reg_T0[ot][reg]();
1415
        break;
1416

    
1417
    case 0x1b6: /* movzbS Gv, Eb */
1418
    case 0x1b7: /* movzwS Gv, Eb */
1419
    case 0x1be: /* movsbS Gv, Eb */
1420
    case 0x1bf: /* movswS Gv, Eb */
1421
        {
1422
            int d_ot;
1423
            /* d_ot is the size of destination */
1424
            d_ot = dflag + OT_WORD;
1425
            /* ot is the size of source */
1426
            ot = (b & 1) + OT_BYTE;
1427
            modrm = ldub(s->pc++);
1428
            reg = ((modrm >> 3) & 7) + OR_EAX;
1429
            mod = (modrm >> 6) & 3;
1430
            rm = modrm & 7;
1431
            
1432
            if (mod == 3) {
1433
                gen_op_mov_TN_reg[ot][0][rm]();
1434
                switch(ot | (b & 8)) {
1435
                case OT_BYTE:
1436
                    gen_op_movzbl_T0_T0();
1437
                    break;
1438
                case OT_BYTE | 8:
1439
                    gen_op_movsbl_T0_T0();
1440
                    break;
1441
                case OT_WORD:
1442
                    gen_op_movzwl_T0_T0();
1443
                    break;
1444
                default:
1445
                case OT_WORD | 8:
1446
                    gen_op_movswl_T0_T0();
1447
                    break;
1448
                }
1449
                gen_op_mov_reg_T0[d_ot][reg]();
1450
            } else {
1451
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1452
                if (b & 8) {
1453
                    gen_op_lds_T0_A0[ot]();
1454
                } else {
1455
                    gen_op_ldu_T0_A0[ot]();
1456
                }
1457
                gen_op_mov_reg_T0[d_ot][reg]();
1458
            }
1459
        }
1460
        break;
1461

    
1462
    case 0x8d: /* lea */
1463
        ot = dflag ? OT_LONG : OT_WORD;
1464
        modrm = ldub(s->pc++);
1465
        reg = (modrm >> 3) & 7;
1466

    
1467
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1468
        gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1469
        break;
1470
        
1471
    case 0xa0: /* mov EAX, Ov */
1472
    case 0xa1:
1473
    case 0xa2: /* mov Ov, EAX */
1474
    case 0xa3:
1475
        if ((b & 1) == 0)
1476
            ot = OT_BYTE;
1477
        else
1478
            ot = dflag ? OT_LONG : OT_WORD;
1479
        if (s->aflag)
1480
            offset_addr = insn_get(s, OT_LONG);
1481
        else
1482
            offset_addr = insn_get(s, OT_WORD);
1483
            
1484
        if ((b & 2) == 0) {
1485
            gen_op_ld_T0_A0[ot]();
1486
            gen_op_mov_reg_T0[ot][R_EAX]();
1487
        } else {
1488
            gen_op_mov_TN_reg[ot][0][R_EAX]();
1489
            gen_op_st_T0_A0[ot]();
1490
        }
1491
        break;
1492

    
1493
    case 0xb0 ... 0xb7: /* mov R, Ib */
1494
        val = insn_get(s, OT_BYTE);
1495
        gen_op1_movl_T0_im(val);
1496
        gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1497
        break;
1498
    case 0xb8 ... 0xbf: /* mov R, Iv */
1499
        ot = dflag ? OT_LONG : OT_WORD;
1500
        val = insn_get(s, ot);
1501
        reg = OR_EAX + (b & 7);
1502
        gen_op1_movl_T0_im(val);
1503
        gen_op_mov_reg_T0[ot][reg]();
1504
        break;
1505

    
1506
    case 0x91 ... 0x97: /* xchg R, EAX */
1507
        ot = dflag ? OT_LONG : OT_WORD;
1508
        reg = b & 7;
1509
        gen_op_mov_TN_reg[ot][0][reg]();
1510
        gen_op_mov_TN_reg[ot][1][R_EAX]();
1511
        gen_op_mov_reg_T0[ot][R_EAX]();
1512
        gen_op_mov_reg_T1[ot][reg]();
1513
        break;
1514
    case 0x86:
1515
    case 0x87: /* xchg Ev, Gv */
1516
        if ((b & 1) == 0)
1517
            ot = OT_BYTE;
1518
        else
1519
            ot = dflag ? OT_LONG : OT_WORD;
1520
        modrm = ldub(s->pc++);
1521
        reg = (modrm >> 3) & 7;
1522

    
1523
        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1524
        gen_op_mov_TN_reg[ot][0][reg]();
1525
        gen_op_ld_T1_A0[ot]();
1526
        gen_op_st_T0_A0[ot]();
1527
        gen_op_mov_reg_T1[ot][reg]();
1528
        break;
1529
        
1530
        /************************/
1531
        /* shifts */
1532
    case 0xc0:
1533
    case 0xc1:
1534
        /* shift Ev,Ib */
1535
        shift = 2;
1536
    grp2:
1537
        {
1538
            if ((b & 1) == 0)
1539
                ot = OT_BYTE;
1540
            else
1541
                ot = dflag ? OT_LONG : OT_WORD;
1542
            
1543
            modrm = ldub(s->pc++);
1544
            mod = (modrm >> 6) & 3;
1545
            rm = modrm & 7;
1546
            op = (modrm >> 3) & 7;
1547
            
1548
            if (mod != 3) {
1549
                gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1550
                gen_op_ld_T0_A0[ot]();
1551
                opreg = OR_TMP0;
1552
            } else {
1553
                opreg = rm + OR_EAX;
1554
            }
1555

    
1556
            /* simpler op */
1557
            if (shift == 0) {
1558
                gen_shift(s, op, ot, opreg, OR_ECX);
1559
            } else {
1560
                if (shift == 2) {
1561
                    shift = ldub(s->pc++);
1562
                }
1563
                gen_shifti(s, op, ot, opreg, shift);
1564
            }
1565

    
1566
            if (mod != 3) {
1567
                gen_op_st_T0_A0[ot]();
1568
            }
1569
        }
1570
        break;
1571
    case 0xd0:
1572
    case 0xd1:
1573
        /* shift Ev,1 */
1574
        shift = 1;
1575
        goto grp2;
1576
    case 0xd2:
1577
    case 0xd3:
1578
        /* shift Ev,cl */
1579
        shift = 0;
1580
        goto grp2;
1581

    
1582
        /************************/
1583
        /* floats */
1584
#if 0        
1585
    case 0xd8 ... 0xdf: 
1586
        modrm = ldub(s->pc++);
1587
        mod = (modrm >> 6) & 3;
1588
        rm = modrm & 7;
1589
        op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1590
        
1591
        if (mod != 3) {
1592
            /* memory op */
1593
            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1594
            switch(op) {
1595
            case 0x00 ... 0x07: /* fxxxs */
1596
            case 0x10 ... 0x17: /* fixxxl */
1597
            case 0x20 ... 0x27: /* fxxxl */
1598
            case 0x30 ... 0x37: /* fixxx */
1599
                {
1600
                    int op1, swap;
1601
                    op1 = fp_ops[op & 7];
1602

1603
                    swap = 0;
1604
                    if ((op & 7) == 5 || (op & 7) == 7)
1605
                        swap = 1;
1606

1607
                    switch(op >> 4) {
1608
                    case 0:
1609
                        ot = OT_LONG;
1610
                        is_int = 0;
1611
                        break;
1612
                    case 1:
1613
                        ot = OT_LONG;
1614
                        is_int = 1;
1615
                        break;
1616
                    case 2:
1617
                        ot = OT_QUAD;
1618
                        is_int = 0;
1619
                        break;
1620
                    case 3:
1621
                    default:
1622
                        ot = OT_WORD;
1623
                        is_int = 1;
1624
                        break;
1625
                    }
1626
                    
1627
                    /* if integer, needs to convert to float */
1628
                    if (is_int) {
1629
                        /* XXX: potential loss of precision if large integer */
1630
                        gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
1631
                        gen_insn2(OP_I2FL, OR_FTMP0, OR_TMP0);
1632
                    } else {
1633
                        gen_ld(OP_LDUB + ot, OR_FTMP0, reg_addr, offset_addr);
1634
                    }
1635
                    if (ot != OT_QUAD)
1636
                        op1 += OP_FADDL - OP_FADDQ;
1637

1638
                    if (!swap)
1639
                        gen_insn3(op1, OR_ST0, OR_ST0, OR_FTMP0);
1640
                    else
1641
                        gen_insn3(op1, OR_ST0, OR_FTMP0, OR_ST0);
1642
                        
1643
                    if ((op & 7) == 3) {
1644
                        /* fcomp needs pop */
1645
                        gen_insn0(OP_FPOP);
1646
                    }
1647
                }
1648
                break;
1649
            case 0x08: /* flds */
1650
            case 0x0a: /* fsts */
1651
            case 0x0b: /* fstps */
1652
            case 0x18: /* fildl */
1653
            case 0x1a: /* fistl */
1654
            case 0x1b: /* fistpl */
1655
            case 0x28: /* fldl */
1656
            case 0x2a: /* fstl */
1657
            case 0x2b: /* fstpl */
1658
            case 0x38: /* filds */
1659
            case 0x3a: /* fists */
1660
            case 0x3b: /* fistps */
1661
                
1662
                switch(op >> 4) {
1663
                case 0:
1664
                    ot = OT_LONG;
1665
                    is_int = 0;
1666
                    break;
1667
                case 1:
1668
                    ot = OT_LONG;
1669
                    is_int = 1;
1670
                    break;
1671
                case 2:
1672
                    ot = OT_QUAD;
1673
                    is_int = 0;
1674
                    break;
1675
                case 3:
1676
                default:
1677
                    ot = OT_WORD;
1678
                    is_int = 1;
1679
                    break;
1680
                }
1681

1682
                switch(op & 7) {
1683
                case 0:
1684
                    gen_insn0(OP_FPUSH);
1685
                    if (is_int) {
1686
                        /* XXX: potential loss of precision */
1687
                        gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
1688
                        gen_insn2(OP_I2FL, OR_ST0, OR_TMP0);
1689
                    } else {
1690
                        gen_ld(OP_LDUB + ot, OR_ST0, reg_addr, offset_addr);
1691
                    }
1692
                    break;
1693
                default:
1694
                    if (is_int) {
1695
                        gen_insn2(OP_F2IL, OR_TMP0, OR_ST0);
1696
                        gen_st(OP_STB + ot, OR_TMP0, reg_addr, offset_addr);
1697
                    } else {
1698
                        gen_st(OP_STB + ot, OR_ST0, reg_addr, offset_addr);
1699
                    }
1700
                    if ((op & 7) == 3)
1701
                        gen_insn0(OP_FPOP);
1702
                    break;
1703
                }
1704
                break;
1705
            case 0x2f: /* fnstsw mem */
1706
                gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
1707
                gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
1708
                break;
1709

1710
            case 0x3c: /* fbld */
1711
            case 0x3e: /* fbstp */
1712
                error("float BCD not hanlded");
1713
                return -1;
1714
            case 0x3d: /* fildll */
1715
                gen_insn0(OP_FPUSH);
1716
                gen_ld(OP_LDQ, OR_TMP0, reg_addr, offset_addr);
1717
                gen_insn2(OP_I2FQ, OR_ST0, OR_TMP0);
1718
                break;
1719
            case 0x3f: /* fistpll */
1720
                gen_insn2(OP_F2IQ, OR_TMP0, OR_ST0);
1721
                gen_st(OP_STQ, OR_TMP0, reg_addr, offset_addr);
1722
                gen_insn0(OP_FPOP);
1723
                break;
1724
            default:
1725
                error("unhandled memory FP\n");
1726
                return -1;
1727
            }
1728
        } else {
1729
            /* register float ops */
1730
            opreg = rm + OR_ST0;
1731

1732
            switch(op) {
1733
            case 0x08: /* fld sti */
1734
                gen_insn0(OP_FPUSH);
1735
                gen_mov(OR_ST0, OR_ST0 + ((rm + 1) & 7));
1736
                break;
1737
            case 0x09: /* fxchg sti */
1738
                gen_mov(OR_TMP0, OR_ST0);
1739
                gen_mov(OR_ST0, opreg);
1740
                gen_mov(opreg, OR_TMP0);
1741
                break;
1742
            case 0x0a: /* grp d9/2 */
1743
                switch(rm) {
1744
                case 0: /* fnop */
1745
                    gen_insn0(OP_NOP);
1746
                    break;
1747
                default:
1748
                    error("unhandled FP GRP d9/2\n");
1749
                    return -1;
1750
                }
1751
                break;
1752
            case 0x0c: /* grp d9/4 */
1753
                switch(rm) {
1754
                case 0: /* fchs */
1755
                    gen_insn3(OP_FSUBQ, OR_ST0, OR_ZERO, OR_ST0);
1756
                    break;
1757
                case 1: /* fabs */
1758
                    gen_insn2(OP_FABSQ, OR_ST0, OR_ST0);
1759
                    break;
1760
                case 4: /* ftst */
1761
                    gen_insn3(OP_CMP, OR_ZERO, OR_ST0, OR_ZERO);
1762
                    break;
1763
                case 5: /* fxam */
1764
                    gen_insn3(OP_FSPECIAL, OR_ZERO, OR_ST0, OR_ZERO);
1765
                    break;
1766
                default:
1767
                    return -1;
1768
                }
1769
                break;
1770
            case 0x0d: /* grp d9/5 */
1771
                {
1772
                    if (rm == 7) {
1773
                        error("bad GRP d9/5");
1774
                        return -1;
1775
                    }
1776
                    /* XXX: needs constant load or symbol table */
1777
                    gen_insn0(OP_FPUSH);
1778
                    gen_ld(OP_LDQ, OR_ST0, OR_ZERO, 
1779
                               (rm * 8) + FLOAT_CONST_ADDR);
1780
                }
1781
                break;
1782
            case 0x0e: /* grp d9/6 */
1783
                switch(rm) {
1784
                case 0: /* f2xm1 */
1785
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
1786
                    break;
1787
                case 1: /* fyl2x */
1788
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
1789
                    gen_insn0(OP_FPOP);
1790
                    break;
1791
                case 2: /* fptan */
1792
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
1793
                    gen_insn0(OP_FPUSH);
1794
                    /* load one */
1795
                    gen_ld(OP_LDQ, OR_ST0, OR_ZERO, 
1796
                               (0 * 8) + FLOAT_CONST_ADDR);
1797
                    break;
1798
                case 3: /* fpatan */
1799
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
1800
                    gen_insn0(OP_FPOP);
1801
                    break;
1802
                case 4: /* fxtract */
1803
                    gen_insn0(OP_FPUSH);
1804
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
1805
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
1806
                    break;
1807
                case 5: /* fprem1 */
1808
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
1809
                    break;
1810
                case 6: /* fdecstp */
1811
                    gen_insn0(OP_FPUSH);
1812
                    break;
1813
                default:
1814
                case 7: /* fdecstp */
1815
                    gen_insn0(OP_FPOP);
1816
                    break;
1817
                }
1818
                break;
1819
            case 0x0f: /* grp d9/7 */
1820
                switch(rm) {
1821
                case 0: /* fprem */
1822
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
1823
                    break;
1824
                case 1: /* fyl2xp1 */
1825
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
1826
                    gen_insn0(OP_FPOP);
1827
                    break;
1828
                case 3: /* fsincos */
1829
                    gen_insn0(OP_FPUSH);
1830
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
1831
                    gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
1832
                    break;
1833
                case 5: /* fscale */
1834
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
1835
                    break;
1836
                case 2: /* fsqrt */
1837
                case 4: /* frndint */
1838
                case 6: /* fsin */
1839
                default:
1840
                case 7: /* fcos */
1841
                    gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
1842
                    break;
1843
                }
1844
                break;
1845
            case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
1846
            case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
1847
            case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
1848
                {
1849
                    int op1, swap;
1850
                    
1851
                    op1 = fp_ops[op & 7];
1852
                    swap = 0;
1853
                    if ((op & 7) == 5 || (op & 7) == 7)
1854
                        swap = 1;
1855
                    if (op >= 0x20) {
1856
                        if (swap) 
1857
                            gen_insn3(op1, opreg, OR_ST0, opreg);
1858
                        else
1859
                            gen_insn3(op1, opreg, opreg, OR_ST0);
1860
                    } else {
1861
                        if (swap)
1862
                            gen_insn3(op1, OR_ST0, opreg, OR_ST0);
1863
                        else
1864
                            gen_insn3(op1, OR_ST0, OR_ST0, opreg);
1865
                    }
1866
                    if (op >= 0x30)
1867
                        gen_insn0(OP_FPOP);
1868
                }
1869
                break;
1870
            case 0x02: /* fcom */
1871
                gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1872
                break;
1873
            case 0x03: /* fcomp */
1874
                gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1875
                gen_insn0(OP_FPOP);
1876
                break;
1877
            case 0x15: /* da/5 */
1878
                switch(rm) {
1879
                case 1: /* fucompp */
1880
                    gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1881
                    gen_insn0(OP_FPOP);
1882
                    gen_insn0(OP_FPOP);
1883
                    break;
1884
                default:
1885
                    return -1;
1886
                }
1887
                break;
1888
            case 0x2a: /* fst sti */
1889
                gen_mov(opreg, OR_ST0);
1890
                break;
1891
            case 0x2b: /* fstp sti */
1892
                gen_mov(opreg, OR_ST0);
1893
                gen_insn0(OP_FPOP);
1894
                break;
1895
            case 0x33: /* de/3 */
1896
                switch(rm) {
1897
                case 1: /* fcompp */
1898
                    gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
1899
                    gen_insn0(OP_FPOP);
1900
                    gen_insn0(OP_FPOP);
1901
                    break;
1902
                default:
1903
                    return -1;
1904
                }
1905
                break;
1906
            case 0x3c: /* df/4 */
1907
                switch(rm) {
1908
                case 0:
1909
                    gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
1910
                    break;
1911
                default:
1912
                    return -1;
1913
                }
1914
                break;
1915
            default:
1916
                error("unhandled FP\n");
1917
                return -1;
1918
            }
1919
        }
1920
        break;
1921
#endif
1922
        /************************/
1923
        /* string ops */
1924
    case 0xa4: /* movsS */
1925
    case 0xa5:
1926
        if ((b & 1) == 0)
1927
            ot = OT_BYTE;
1928
        else
1929
            ot = dflag ? OT_LONG : OT_WORD;
1930
        if (prefixes & PREFIX_REPZ) {
1931
            gen_op_movs[3 + ot]();
1932
        } else {
1933
            gen_op_movs[ot]();
1934
        }
1935
        break;
1936
        
1937
    case 0xaa: /* stosS */
1938
    case 0xab:
1939
        if ((b & 1) == 0)
1940
            ot = OT_BYTE;
1941
        else
1942
            ot = dflag ? OT_LONG : OT_WORD;
1943
        if (prefixes & PREFIX_REPZ) {
1944
            gen_op_stos[3 + ot]();
1945
        } else {
1946
            gen_op_stos[ot]();
1947
        }
1948
        break;
1949
    case 0xac: /* lodsS */
1950
    case 0xad:
1951
        if ((b & 1) == 0)
1952
            ot = OT_BYTE;
1953
        else
1954
            ot = dflag ? OT_LONG : OT_WORD;
1955
        if (prefixes & PREFIX_REPZ) {
1956
            gen_op_lods[3 + ot]();
1957
        } else {
1958
            gen_op_lods[ot]();
1959
        }
1960
        break;
1961
    case 0xae: /* scasS */
1962
    case 0xaf:
1963
        if ((b & 1) == 0)
1964
            ot = OT_BYTE;
1965
        else
1966
            ot = dflag ? OT_LONG : OT_WORD;
1967
        if (prefixes & PREFIX_REPNZ) {
1968
            gen_op_scas[6 + ot]();
1969
        } else if (prefixes & PREFIX_REPZ) {
1970
            gen_op_scas[3 + ot]();
1971
        } else {
1972
            gen_op_scas[ot]();
1973
        }
1974
        break;
1975

    
1976
    case 0xa6: /* cmpsS */
1977
    case 0xa7:
1978
        if ((b & 1) == 0)
1979
            ot = OT_BYTE;
1980
        else
1981
            ot = dflag ? OT_LONG : OT_WORD;
1982
        if (prefixes & PREFIX_REPNZ) {
1983
            gen_op_cmps[6 + ot]();
1984
        } else if (prefixes & PREFIX_REPZ) {
1985
            gen_op_cmps[3 + ot]();
1986
        } else {
1987
            gen_op_cmps[ot]();
1988
        }
1989
        break;
1990
        
1991
    case 0x6c: /* insS */
1992
    case 0x6d:
1993
        if ((b & 1) == 0)
1994
            ot = OT_BYTE;
1995
        else
1996
            ot = dflag ? OT_LONG : OT_WORD;
1997
        if (prefixes & PREFIX_REPZ) {
1998
            gen_op_ins[3 + ot]();
1999
        } else {
2000
            gen_op_ins[ot]();
2001
        }
2002
        break;
2003
    case 0x6e: /* outsS */
2004
    case 0x6f:
2005
        if ((b & 1) == 0)
2006
            ot = OT_BYTE;
2007
        else
2008
            ot = dflag ? OT_LONG : OT_WORD;
2009
        if (prefixes & PREFIX_REPZ) {
2010
            gen_op_outs[3 + ot]();
2011
        } else {
2012
            gen_op_outs[ot]();
2013
        }
2014
        break;
2015

    
2016
        /************************/
2017
        /* control */
2018
    case 0xc2: /* ret im */
2019
        /* XXX: handle stack pop ? */
2020
        val = ldsw(s->pc);
2021
        s->pc += 2;
2022
        gen_op_popl_T0();
2023
        gen_op_addl_ESP_im(val);
2024
        gen_op_jmp_T0();
2025
        break;
2026
    case 0xc3: /* ret */
2027
        gen_op_popl_T0();
2028
        gen_op_jmp_T0();
2029
        break;
2030
    case 0xe8: /* call */
2031
        val = insn_get(s, OT_LONG);
2032
        val += (long)s->pc;
2033
        gen_op1_movl_T1_im((long)s->pc);
2034
        gen_op_pushl_T1();
2035
        gen_op_jmp_im(val);
2036
        break;
2037
    case 0xe9: /* jmp */
2038
        val = insn_get(s, OT_LONG);
2039
        val += (long)s->pc;
2040
        gen_op_jmp_im(val);
2041
        break;
2042
    case 0xeb: /* jmp Jb */
2043
        val = (int8_t)insn_get(s, OT_BYTE);
2044
        val += (long)s->pc;
2045
        gen_op_jmp_im(val);
2046
        break;
2047
    case 0x70 ... 0x7f: /* jcc Jb */
2048
        val = (int8_t)insn_get(s, OT_BYTE);
2049
        val += (long)s->pc;
2050
        goto do_jcc;
2051
    case 0x180 ... 0x18f: /* jcc Jv */
2052
        if (dflag) {
2053
            val = insn_get(s, OT_LONG);
2054
        } else {
2055
            val = (int16_t)insn_get(s, OT_WORD); 
2056
        }
2057
        val += (long)s->pc; /* XXX: fix 16 bit wrap */
2058
    do_jcc:
2059
        gen_jcc(s, b, val);
2060
        break;
2061

    
2062
    case 0x190 ... 0x19f:
2063
        modrm = ldub(s->pc++);
2064
        gen_setcc(s, b);
2065
        gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2066
        break;
2067

    
2068
        /************************/
2069
        /* flags */
2070
    case 0x9c: /* pushf */
2071
        gen_op_movl_T0_eflags();
2072
        gen_op_pushl_T0();
2073
        break;
2074
    case 0x9d: /* popf */
2075
        gen_op_popl_T0();
2076
        gen_op_movl_eflags_T0();
2077
        s->cc_op = CC_OP_EFLAGS;
2078
        break;
2079
    case 0x9e: /* sahf */
2080
        gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2081
        if (s->cc_op != CC_OP_DYNAMIC)
2082
            op_set_cc_op(s->cc_op);
2083
        gen_op_movb_eflags_T0();
2084
        s->cc_op = CC_OP_EFLAGS;
2085
        break;
2086
    case 0x9f: /* lahf */
2087
        if (s->cc_op != CC_OP_DYNAMIC)
2088
            op_set_cc_op(s->cc_op);
2089
        gen_op_movl_T0_eflags();
2090
        gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2091
        break;
2092
    case 0xf5: /* cmc */
2093
        if (s->cc_op != CC_OP_DYNAMIC)
2094
            op_set_cc_op(s->cc_op);
2095
        gen_op_cmc();
2096
        s->cc_op = CC_OP_EFLAGS;
2097
        break;
2098
    case 0xf8: /* clc */
2099
        if (s->cc_op != CC_OP_DYNAMIC)
2100
            op_set_cc_op(s->cc_op);
2101
        gen_op_clc();
2102
        s->cc_op = CC_OP_EFLAGS;
2103
        break;
2104
    case 0xf9: /* stc */
2105
        if (s->cc_op != CC_OP_DYNAMIC)
2106
            op_set_cc_op(s->cc_op);
2107
        gen_op_stc();
2108
        s->cc_op = CC_OP_EFLAGS;
2109
        break;
2110
    case 0xfc: /* cld */
2111
        gen_op_cld();
2112
        break;
2113
    case 0xfd: /* std */
2114
        gen_op_std();
2115
        break;
2116

    
2117
        /************************/
2118
        /* misc */
2119
    case 0x90: /* nop */
2120
        break;
2121

    
2122
#if 0        
2123
    case 0x1a2: /* cpuid */
2124
        gen_insn0(OP_ASM);
2125
        break;
2126
#endif
2127
    default:
2128
        error("unknown opcode %x", b);
2129
        return -1;
2130
    }
2131
    return (long)s->pc;
2132
}
2133