Statistics
| Branch: | Revision:

root / target-i386 / op.c @ 07d2c595

History | View | Annotate | Download (13.4 kB)

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

    
21
#define ASM_SOFTMMU
22
#include "exec.h"
23

    
24
/* we define the various pieces of code used by the JIT */
25

    
26
#define REG EAX
27
#define REGNAME _EAX
28
#include "opreg_template.h"
29
#undef REG
30
#undef REGNAME
31

    
32
#define REG ECX
33
#define REGNAME _ECX
34
#include "opreg_template.h"
35
#undef REG
36
#undef REGNAME
37

    
38
#define REG EDX
39
#define REGNAME _EDX
40
#include "opreg_template.h"
41
#undef REG
42
#undef REGNAME
43

    
44
#define REG EBX
45
#define REGNAME _EBX
46
#include "opreg_template.h"
47
#undef REG
48
#undef REGNAME
49

    
50
#define REG ESP
51
#define REGNAME _ESP
52
#include "opreg_template.h"
53
#undef REG
54
#undef REGNAME
55

    
56
#define REG EBP
57
#define REGNAME _EBP
58
#include "opreg_template.h"
59
#undef REG
60
#undef REGNAME
61

    
62
#define REG ESI
63
#define REGNAME _ESI
64
#include "opreg_template.h"
65
#undef REG
66
#undef REGNAME
67

    
68
#define REG EDI
69
#define REGNAME _EDI
70
#include "opreg_template.h"
71
#undef REG
72
#undef REGNAME
73

    
74
#ifdef TARGET_X86_64
75

    
76
#define REG (env->regs[8])
77
#define REGNAME _R8
78
#include "opreg_template.h"
79
#undef REG
80
#undef REGNAME
81

    
82
#define REG (env->regs[9])
83
#define REGNAME _R9
84
#include "opreg_template.h"
85
#undef REG
86
#undef REGNAME
87

    
88
#define REG (env->regs[10])
89
#define REGNAME _R10
90
#include "opreg_template.h"
91
#undef REG
92
#undef REGNAME
93

    
94
#define REG (env->regs[11])
95
#define REGNAME _R11
96
#include "opreg_template.h"
97
#undef REG
98
#undef REGNAME
99

    
100
#define REG (env->regs[12])
101
#define REGNAME _R12
102
#include "opreg_template.h"
103
#undef REG
104
#undef REGNAME
105

    
106
#define REG (env->regs[13])
107
#define REGNAME _R13
108
#include "opreg_template.h"
109
#undef REG
110
#undef REGNAME
111

    
112
#define REG (env->regs[14])
113
#define REGNAME _R14
114
#include "opreg_template.h"
115
#undef REG
116
#undef REGNAME
117

    
118
#define REG (env->regs[15])
119
#define REGNAME _R15
120
#include "opreg_template.h"
121
#undef REG
122
#undef REGNAME
123

    
124
#endif
125

    
126
/* multiply/divide */
127

    
128
/* XXX: add eflags optimizations */
129
/* XXX: add non P4 style flags */
130

    
131
void OPPROTO op_mulb_AL_T0(void)
132
{
133
    unsigned int res;
134
    res = (uint8_t)EAX * (uint8_t)T0;
135
    EAX = (EAX & ~0xffff) | res;
136
    CC_DST = res;
137
    CC_SRC = (res & 0xff00);
138
}
139

    
140
void OPPROTO op_imulb_AL_T0(void)
141
{
142
    int res;
143
    res = (int8_t)EAX * (int8_t)T0;
144
    EAX = (EAX & ~0xffff) | (res & 0xffff);
145
    CC_DST = res;
146
    CC_SRC = (res != (int8_t)res);
147
}
148

    
149
void OPPROTO op_mulw_AX_T0(void)
150
{
151
    unsigned int res;
152
    res = (uint16_t)EAX * (uint16_t)T0;
153
    EAX = (EAX & ~0xffff) | (res & 0xffff);
154
    EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
155
    CC_DST = res;
156
    CC_SRC = res >> 16;
157
}
158

    
159
void OPPROTO op_imulw_AX_T0(void)
160
{
161
    int res;
162
    res = (int16_t)EAX * (int16_t)T0;
163
    EAX = (EAX & ~0xffff) | (res & 0xffff);
164
    EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff);
165
    CC_DST = res;
166
    CC_SRC = (res != (int16_t)res);
167
}
168

    
169
void OPPROTO op_mull_EAX_T0(void)
170
{
171
    uint64_t res;
172
    res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
173
    EAX = (uint32_t)res;
174
    EDX = (uint32_t)(res >> 32);
175
    CC_DST = (uint32_t)res;
176
    CC_SRC = (uint32_t)(res >> 32);
177
}
178

    
179
void OPPROTO op_imull_EAX_T0(void)
180
{
181
    int64_t res;
182
    res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
183
    EAX = (uint32_t)(res);
184
    EDX = (uint32_t)(res >> 32);
185
    CC_DST = res;
186
    CC_SRC = (res != (int32_t)res);
187
}
188

    
189
void OPPROTO op_imulw_T0_T1(void)
190
{
191
    int res;
192
    res = (int16_t)T0 * (int16_t)T1;
193
    T0 = res;
194
    CC_DST = res;
195
    CC_SRC = (res != (int16_t)res);
196
}
197

    
198
void OPPROTO op_imull_T0_T1(void)
199
{
200
    int64_t res;
201
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
202
    T0 = res;
203
    CC_DST = res;
204
    CC_SRC = (res != (int32_t)res);
205
}
206

    
207
#ifdef TARGET_X86_64
208
void OPPROTO op_mulq_EAX_T0(void)
209
{
210
    helper_mulq_EAX_T0(T0);
211
}
212

    
213
void OPPROTO op_imulq_EAX_T0(void)
214
{
215
    helper_imulq_EAX_T0(T0);
216
}
217

    
218
void OPPROTO op_imulq_T0_T1(void)
219
{
220
    T0 = helper_imulq_T0_T1(T0, T1);
221
}
222
#endif
223

    
224
/* constant load & misc op */
225

    
226
/* XXX: consistent names */
227
void OPPROTO op_addl_T1_im(void)
228
{
229
    T1 += PARAM1;
230
}
231

    
232
void OPPROTO op_movl_T1_A0(void)
233
{
234
    T1 = A0;
235
}
236

    
237
void OPPROTO op_addl_A0_AL(void)
238
{
239
    A0 = (uint32_t)(A0 + (EAX & 0xff));
240
}
241

    
242
#ifdef TARGET_X86_64
243

    
244
void OPPROTO op_addq_A0_AL(void)
245
{
246
    A0 = (A0 + (EAX & 0xff));
247
}
248

    
249
#endif
250

    
251
void OPPROTO op_into(void)
252
{
253
    int eflags;
254
    eflags = cc_table[CC_OP].compute_all();
255
    if (eflags & CC_O) {
256
        raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
257
    }
258
    FORCE_RET();
259
}
260

    
261
void OPPROTO op_cmpxchg8b(void)
262
{
263
    helper_cmpxchg8b(A0);
264
}
265

    
266
/* multiple size ops */
267

    
268
#define ldul ldl
269

    
270
#define SHIFT 0
271
#include "ops_template.h"
272
#undef SHIFT
273

    
274
#define SHIFT 1
275
#include "ops_template.h"
276
#undef SHIFT
277

    
278
#define SHIFT 2
279
#include "ops_template.h"
280
#undef SHIFT
281

    
282
#ifdef TARGET_X86_64
283

    
284
#define SHIFT 3
285
#include "ops_template.h"
286
#undef SHIFT
287

    
288
#endif
289

    
290
/* sign extend */
291

    
292
void OPPROTO op_movsbl_T0_T0(void)
293
{
294
    T0 = (int8_t)T0;
295
}
296

    
297
void OPPROTO op_movzbl_T0_T0(void)
298
{
299
    T0 = (uint8_t)T0;
300
}
301

    
302
void OPPROTO op_movswl_T0_T0(void)
303
{
304
    T0 = (int16_t)T0;
305
}
306

    
307
void OPPROTO op_movzwl_T0_T0(void)
308
{
309
    T0 = (uint16_t)T0;
310
}
311

    
312
void OPPROTO op_movswl_EAX_AX(void)
313
{
314
    EAX = (uint32_t)((int16_t)EAX);
315
}
316

    
317
#ifdef TARGET_X86_64
318
void OPPROTO op_movslq_T0_T0(void)
319
{
320
    T0 = (int32_t)T0;
321
}
322

    
323
void OPPROTO op_movslq_RAX_EAX(void)
324
{
325
    EAX = (int32_t)EAX;
326
}
327
#endif
328

    
329
void OPPROTO op_movsbw_AX_AL(void)
330
{
331
    EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);
332
}
333

    
334
void OPPROTO op_movslq_EDX_EAX(void)
335
{
336
    EDX = (uint32_t)((int32_t)EAX >> 31);
337
}
338

    
339
void OPPROTO op_movswl_DX_AX(void)
340
{
341
    EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff);
342
}
343

    
344
#ifdef TARGET_X86_64
345
void OPPROTO op_movsqo_RDX_RAX(void)
346
{
347
    EDX = (int64_t)EAX >> 63;
348
}
349
#endif
350

    
351
/* string ops helpers */
352

    
353
void OPPROTO op_addl_ESI_T0(void)
354
{
355
    ESI = (uint32_t)(ESI + T0);
356
}
357

    
358
void OPPROTO op_addw_ESI_T0(void)
359
{
360
    ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
361
}
362

    
363
void OPPROTO op_addl_EDI_T0(void)
364
{
365
    EDI = (uint32_t)(EDI + T0);
366
}
367

    
368
void OPPROTO op_addw_EDI_T0(void)
369
{
370
    EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
371
}
372

    
373
void OPPROTO op_decl_ECX(void)
374
{
375
    ECX = (uint32_t)(ECX - 1);
376
}
377

    
378
void OPPROTO op_decw_ECX(void)
379
{
380
    ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
381
}
382

    
383
#ifdef TARGET_X86_64
384
void OPPROTO op_addq_ESI_T0(void)
385
{
386
    ESI = (ESI + T0);
387
}
388

    
389
void OPPROTO op_addq_EDI_T0(void)
390
{
391
    EDI = (EDI + T0);
392
}
393

    
394
void OPPROTO op_decq_ECX(void)
395
{
396
    ECX--;
397
}
398
#endif
399

    
400
/* bcd */
401

    
402
void OPPROTO op_aam(void)
403
{
404
    helper_aam(PARAM1);
405
}
406

    
407
void OPPROTO op_aad(void)
408
{
409
    helper_aad(PARAM1);
410
}
411

    
412
void OPPROTO op_aaa(void)
413
{
414
    helper_aaa();
415
}
416

    
417
void OPPROTO op_aas(void)
418
{
419
    helper_aas();
420
}
421

    
422
void OPPROTO op_daa(void)
423
{
424
    helper_daa();
425
}
426

    
427
void OPPROTO op_das(void)
428
{
429
    helper_das();
430
}
431

    
432
/* segment handling */
433

    
434
/* faster VM86 version */
435
void OPPROTO op_movl_seg_T0_vm(void)
436
{
437
    int selector;
438
    SegmentCache *sc;
439

    
440
    selector = T0 & 0xffff;
441
    /* env->segs[] access */
442
    sc = (SegmentCache *)((char *)env + PARAM1);
443
    sc->selector = selector;
444
    sc->base = (selector << 4);
445
}
446

    
447
void OPPROTO op_movl_T0_seg(void)
448
{
449
    T0 = env->segs[PARAM1].selector;
450
}
451

    
452
void OPPROTO op_lsl(void)
453
{
454
    uint32_t val;
455
    val = helper_lsl(T0);
456
    if (CC_SRC & CC_Z)
457
        T1 = val;
458
    FORCE_RET();
459
}
460

    
461
void OPPROTO op_lar(void)
462
{
463
    uint32_t val;
464
    val = helper_lar(T0);
465
    if (CC_SRC & CC_Z)
466
        T1 = val;
467
    FORCE_RET();
468
}
469

    
470
void OPPROTO op_verr(void)
471
{
472
    helper_verr(T0);
473
}
474

    
475
void OPPROTO op_verw(void)
476
{
477
    helper_verw(T0);
478
}
479

    
480
void OPPROTO op_arpl(void)
481
{
482
    if ((T0 & 3) < (T1 & 3)) {
483
        /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
484
        T0 = (T0 & ~3) | (T1 & 3);
485
        T1 = CC_Z;
486
   } else {
487
        T1 = 0;
488
    }
489
    FORCE_RET();
490
}
491

    
492
void OPPROTO op_arpl_update(void)
493
{
494
    int eflags;
495
    eflags = cc_table[CC_OP].compute_all();
496
    CC_SRC = (eflags & ~CC_Z) | T1;
497
}
498

    
499
void OPPROTO op_movl_T0_env(void)
500
{
501
    T0 = *(uint32_t *)((char *)env + PARAM1);
502
}
503

    
504
void OPPROTO op_movl_env_T0(void)
505
{
506
    *(uint32_t *)((char *)env + PARAM1) = T0;
507
}
508

    
509
void OPPROTO op_movl_env_T1(void)
510
{
511
    *(uint32_t *)((char *)env + PARAM1) = T1;
512
}
513

    
514
void OPPROTO op_movtl_T0_env(void)
515
{
516
    T0 = *(target_ulong *)((char *)env + PARAM1);
517
}
518

    
519
void OPPROTO op_movtl_env_T0(void)
520
{
521
    *(target_ulong *)((char *)env + PARAM1) = T0;
522
}
523

    
524
void OPPROTO op_movtl_T1_env(void)
525
{
526
    T1 = *(target_ulong *)((char *)env + PARAM1);
527
}
528

    
529
void OPPROTO op_movtl_env_T1(void)
530
{
531
    *(target_ulong *)((char *)env + PARAM1) = T1;
532
}
533

    
534
/* flags handling */
535

    
536
void OPPROTO op_jmp_label(void)
537
{
538
    GOTO_LABEL_PARAM(1);
539
}
540

    
541
void OPPROTO op_jnz_T0_label(void)
542
{
543
    if (T0)
544
        GOTO_LABEL_PARAM(1);
545
    FORCE_RET();
546
}
547

    
548
void OPPROTO op_jz_T0_label(void)
549
{
550
    if (!T0)
551
        GOTO_LABEL_PARAM(1);
552
    FORCE_RET();
553
}
554

    
555
/* slow set cases (compute x86 flags) */
556
void OPPROTO op_seto_T0_cc(void)
557
{
558
    int eflags;
559
    eflags = cc_table[CC_OP].compute_all();
560
    T0 = (eflags >> 11) & 1;
561
}
562

    
563
void OPPROTO op_setb_T0_cc(void)
564
{
565
    T0 = cc_table[CC_OP].compute_c();
566
}
567

    
568
void OPPROTO op_setz_T0_cc(void)
569
{
570
    int eflags;
571
    eflags = cc_table[CC_OP].compute_all();
572
    T0 = (eflags >> 6) & 1;
573
}
574

    
575
void OPPROTO op_setbe_T0_cc(void)
576
{
577
    int eflags;
578
    eflags = cc_table[CC_OP].compute_all();
579
    T0 = (eflags & (CC_Z | CC_C)) != 0;
580
}
581

    
582
void OPPROTO op_sets_T0_cc(void)
583
{
584
    int eflags;
585
    eflags = cc_table[CC_OP].compute_all();
586
    T0 = (eflags >> 7) & 1;
587
}
588

    
589
void OPPROTO op_setp_T0_cc(void)
590
{
591
    int eflags;
592
    eflags = cc_table[CC_OP].compute_all();
593
    T0 = (eflags >> 2) & 1;
594
}
595

    
596
void OPPROTO op_setl_T0_cc(void)
597
{
598
    int eflags;
599
    eflags = cc_table[CC_OP].compute_all();
600
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
601
}
602

    
603
void OPPROTO op_setle_T0_cc(void)
604
{
605
    int eflags;
606
    eflags = cc_table[CC_OP].compute_all();
607
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
608
}
609

    
610
void OPPROTO op_xor_T0_1(void)
611
{
612
    T0 ^= 1;
613
}
614

    
615
void OPPROTO op_mov_T0_cc(void)
616
{
617
    T0 = cc_table[CC_OP].compute_all();
618
}
619

    
620
/* XXX: clear VIF/VIP in all ops ? */
621

    
622
void OPPROTO op_movl_eflags_T0(void)
623
{
624
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
625
}
626

    
627
void OPPROTO op_movw_eflags_T0(void)
628
{
629
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
630
}
631

    
632
void OPPROTO op_movl_eflags_T0_io(void)
633
{
634
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
635
}
636

    
637
void OPPROTO op_movw_eflags_T0_io(void)
638
{
639
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
640
}
641

    
642
void OPPROTO op_movl_eflags_T0_cpl0(void)
643
{
644
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
645
}
646

    
647
void OPPROTO op_movw_eflags_T0_cpl0(void)
648
{
649
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
650
}
651

    
652
#if 0
653
/* vm86plus version */
654
void OPPROTO op_movw_eflags_T0_vm(void)
655
{
656
    int eflags;
657
    eflags = T0;
658
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
659
    DF = 1 - (2 * ((eflags >> 10) & 1));
660
    /* we also update some system flags as in user mode */
661
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
662
        (eflags & FL_UPDATE_MASK16);
663
    if (eflags & IF_MASK) {
664
        env->eflags |= VIF_MASK;
665
        if (env->eflags & VIP_MASK) {
666
            EIP = PARAM1;
667
            raise_exception(EXCP0D_GPF);
668
        }
669
    }
670
    FORCE_RET();
671
}
672

673
void OPPROTO op_movl_eflags_T0_vm(void)
674
{
675
    int eflags;
676
    eflags = T0;
677
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
678
    DF = 1 - (2 * ((eflags >> 10) & 1));
679
    /* we also update some system flags as in user mode */
680
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
681
        (eflags & FL_UPDATE_MASK32);
682
    if (eflags & IF_MASK) {
683
        env->eflags |= VIF_MASK;
684
        if (env->eflags & VIP_MASK) {
685
            EIP = PARAM1;
686
            raise_exception(EXCP0D_GPF);
687
        }
688
    }
689
    FORCE_RET();
690
}
691
#endif
692

    
693
/* XXX: compute only O flag */
694
void OPPROTO op_movb_eflags_T0(void)
695
{
696
    int of;
697
    of = cc_table[CC_OP].compute_all() & CC_O;
698
    CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
699
}
700

    
701
void OPPROTO op_movl_T0_eflags(void)
702
{
703
    int eflags;
704
    eflags = cc_table[CC_OP].compute_all();
705
    eflags |= (DF & DF_MASK);
706
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
707
    T0 = eflags;
708
}
709

    
710
/* vm86plus version */
711
#if 0
712
void OPPROTO op_movl_T0_eflags_vm(void)
713
{
714
    int eflags;
715
    eflags = cc_table[CC_OP].compute_all();
716
    eflags |= (DF & DF_MASK);
717
    eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
718
    if (env->eflags & VIF_MASK)
719
        eflags |= IF_MASK;
720
    T0 = eflags;
721
}
722
#endif
723

    
724
void OPPROTO op_clc(void)
725
{
726
    int eflags;
727
    eflags = cc_table[CC_OP].compute_all();
728
    eflags &= ~CC_C;
729
    CC_SRC = eflags;
730
}
731

    
732
void OPPROTO op_stc(void)
733
{
734
    int eflags;
735
    eflags = cc_table[CC_OP].compute_all();
736
    eflags |= CC_C;
737
    CC_SRC = eflags;
738
}
739

    
740
void OPPROTO op_cmc(void)
741
{
742
    int eflags;
743
    eflags = cc_table[CC_OP].compute_all();
744
    eflags ^= CC_C;
745
    CC_SRC = eflags;
746
}
747

    
748
void OPPROTO op_salc(void)
749
{
750
    int cf;
751
    cf = cc_table[CC_OP].compute_c();
752
    EAX = (EAX & ~0xff) | ((-cf) & 0xff);
753
}
754

    
755
void OPPROTO op_fcomi_dummy(void)
756
{
757
    T0 = 0;
758
}
759

    
760
/* SSE support */
761
void OPPROTO op_com_dummy(void)
762
{
763
    T0 = 0;
764
}