Statistics
| Branch: | Revision:

root / target-i386 / op.c @ 6e0d8677

History | View | Annotate | Download (11.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_into(void)
228
{
229
    int eflags;
230
    eflags = cc_table[CC_OP].compute_all();
231
    if (eflags & CC_O) {
232
        raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
233
    }
234
    FORCE_RET();
235
}
236

    
237
void OPPROTO op_cmpxchg8b(void)
238
{
239
    helper_cmpxchg8b(A0);
240
}
241

    
242
/* multiple size ops */
243

    
244
#define ldul ldl
245

    
246
#define SHIFT 0
247
#include "ops_template.h"
248
#undef SHIFT
249

    
250
#define SHIFT 1
251
#include "ops_template.h"
252
#undef SHIFT
253

    
254
#define SHIFT 2
255
#include "ops_template.h"
256
#undef SHIFT
257

    
258
#ifdef TARGET_X86_64
259

    
260
#define SHIFT 3
261
#include "ops_template.h"
262
#undef SHIFT
263

    
264
#endif
265

    
266
/* bcd */
267

    
268
void OPPROTO op_aam(void)
269
{
270
    helper_aam(PARAM1);
271
}
272

    
273
void OPPROTO op_aad(void)
274
{
275
    helper_aad(PARAM1);
276
}
277

    
278
void OPPROTO op_aaa(void)
279
{
280
    helper_aaa();
281
}
282

    
283
void OPPROTO op_aas(void)
284
{
285
    helper_aas();
286
}
287

    
288
void OPPROTO op_daa(void)
289
{
290
    helper_daa();
291
}
292

    
293
void OPPROTO op_das(void)
294
{
295
    helper_das();
296
}
297

    
298
/* segment handling */
299

    
300
/* faster VM86 version */
301
void OPPROTO op_movl_seg_T0_vm(void)
302
{
303
    int selector;
304
    SegmentCache *sc;
305

    
306
    selector = T0 & 0xffff;
307
    /* env->segs[] access */
308
    sc = (SegmentCache *)((char *)env + PARAM1);
309
    sc->selector = selector;
310
    sc->base = (selector << 4);
311
}
312

    
313
void OPPROTO op_movl_T0_seg(void)
314
{
315
    T0 = env->segs[PARAM1].selector;
316
}
317

    
318
void OPPROTO op_lsl(void)
319
{
320
    uint32_t val;
321
    val = helper_lsl(T0);
322
    if (CC_SRC & CC_Z)
323
        T1 = val;
324
    FORCE_RET();
325
}
326

    
327
void OPPROTO op_lar(void)
328
{
329
    uint32_t val;
330
    val = helper_lar(T0);
331
    if (CC_SRC & CC_Z)
332
        T1 = val;
333
    FORCE_RET();
334
}
335

    
336
void OPPROTO op_verr(void)
337
{
338
    helper_verr(T0);
339
}
340

    
341
void OPPROTO op_verw(void)
342
{
343
    helper_verw(T0);
344
}
345

    
346
void OPPROTO op_arpl(void)
347
{
348
    if ((T0 & 3) < (T1 & 3)) {
349
        /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
350
        T0 = (T0 & ~3) | (T1 & 3);
351
        T1 = CC_Z;
352
   } else {
353
        T1 = 0;
354
    }
355
    FORCE_RET();
356
}
357

    
358
void OPPROTO op_arpl_update(void)
359
{
360
    int eflags;
361
    eflags = cc_table[CC_OP].compute_all();
362
    CC_SRC = (eflags & ~CC_Z) | T1;
363
}
364

    
365
void OPPROTO op_movl_T0_env(void)
366
{
367
    T0 = *(uint32_t *)((char *)env + PARAM1);
368
}
369

    
370
void OPPROTO op_movl_env_T0(void)
371
{
372
    *(uint32_t *)((char *)env + PARAM1) = T0;
373
}
374

    
375
void OPPROTO op_movl_env_T1(void)
376
{
377
    *(uint32_t *)((char *)env + PARAM1) = T1;
378
}
379

    
380
void OPPROTO op_movtl_T0_env(void)
381
{
382
    T0 = *(target_ulong *)((char *)env + PARAM1);
383
}
384

    
385
void OPPROTO op_movtl_env_T0(void)
386
{
387
    *(target_ulong *)((char *)env + PARAM1) = T0;
388
}
389

    
390
void OPPROTO op_movtl_T1_env(void)
391
{
392
    T1 = *(target_ulong *)((char *)env + PARAM1);
393
}
394

    
395
void OPPROTO op_movtl_env_T1(void)
396
{
397
    *(target_ulong *)((char *)env + PARAM1) = T1;
398
}
399

    
400
/* flags handling */
401

    
402
void OPPROTO op_jmp_label(void)
403
{
404
    GOTO_LABEL_PARAM(1);
405
}
406

    
407
void OPPROTO op_jnz_T0_label(void)
408
{
409
    if (T0)
410
        GOTO_LABEL_PARAM(1);
411
    FORCE_RET();
412
}
413

    
414
/* slow set cases (compute x86 flags) */
415
void OPPROTO op_seto_T0_cc(void)
416
{
417
    int eflags;
418
    eflags = cc_table[CC_OP].compute_all();
419
    T0 = (eflags >> 11) & 1;
420
}
421

    
422
void OPPROTO op_setb_T0_cc(void)
423
{
424
    T0 = cc_table[CC_OP].compute_c();
425
}
426

    
427
void OPPROTO op_setz_T0_cc(void)
428
{
429
    int eflags;
430
    eflags = cc_table[CC_OP].compute_all();
431
    T0 = (eflags >> 6) & 1;
432
}
433

    
434
void OPPROTO op_setbe_T0_cc(void)
435
{
436
    int eflags;
437
    eflags = cc_table[CC_OP].compute_all();
438
    T0 = (eflags & (CC_Z | CC_C)) != 0;
439
}
440

    
441
void OPPROTO op_sets_T0_cc(void)
442
{
443
    int eflags;
444
    eflags = cc_table[CC_OP].compute_all();
445
    T0 = (eflags >> 7) & 1;
446
}
447

    
448
void OPPROTO op_setp_T0_cc(void)
449
{
450
    int eflags;
451
    eflags = cc_table[CC_OP].compute_all();
452
    T0 = (eflags >> 2) & 1;
453
}
454

    
455
void OPPROTO op_setl_T0_cc(void)
456
{
457
    int eflags;
458
    eflags = cc_table[CC_OP].compute_all();
459
    T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
460
}
461

    
462
void OPPROTO op_setle_T0_cc(void)
463
{
464
    int eflags;
465
    eflags = cc_table[CC_OP].compute_all();
466
    T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
467
}
468

    
469
void OPPROTO op_xor_T0_1(void)
470
{
471
    T0 ^= 1;
472
}
473

    
474
/* XXX: clear VIF/VIP in all ops ? */
475

    
476
void OPPROTO op_movl_eflags_T0(void)
477
{
478
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
479
}
480

    
481
void OPPROTO op_movw_eflags_T0(void)
482
{
483
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
484
}
485

    
486
void OPPROTO op_movl_eflags_T0_io(void)
487
{
488
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
489
}
490

    
491
void OPPROTO op_movw_eflags_T0_io(void)
492
{
493
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
494
}
495

    
496
void OPPROTO op_movl_eflags_T0_cpl0(void)
497
{
498
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
499
}
500

    
501
void OPPROTO op_movw_eflags_T0_cpl0(void)
502
{
503
    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
504
}
505

    
506
#if 0
507
/* vm86plus version */
508
void OPPROTO op_movw_eflags_T0_vm(void)
509
{
510
    int eflags;
511
    eflags = T0;
512
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
513
    DF = 1 - (2 * ((eflags >> 10) & 1));
514
    /* we also update some system flags as in user mode */
515
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
516
        (eflags & FL_UPDATE_MASK16);
517
    if (eflags & IF_MASK) {
518
        env->eflags |= VIF_MASK;
519
        if (env->eflags & VIP_MASK) {
520
            EIP = PARAM1;
521
            raise_exception(EXCP0D_GPF);
522
        }
523
    }
524
    FORCE_RET();
525
}
526

527
void OPPROTO op_movl_eflags_T0_vm(void)
528
{
529
    int eflags;
530
    eflags = T0;
531
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
532
    DF = 1 - (2 * ((eflags >> 10) & 1));
533
    /* we also update some system flags as in user mode */
534
    env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
535
        (eflags & FL_UPDATE_MASK32);
536
    if (eflags & IF_MASK) {
537
        env->eflags |= VIF_MASK;
538
        if (env->eflags & VIP_MASK) {
539
            EIP = PARAM1;
540
            raise_exception(EXCP0D_GPF);
541
        }
542
    }
543
    FORCE_RET();
544
}
545
#endif
546

    
547
/* XXX: compute only O flag */
548
void OPPROTO op_movb_eflags_T0(void)
549
{
550
    int of;
551
    of = cc_table[CC_OP].compute_all() & CC_O;
552
    CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
553
}
554

    
555
void OPPROTO op_movl_T0_eflags(void)
556
{
557
    int eflags;
558
    eflags = cc_table[CC_OP].compute_all();
559
    eflags |= (DF & DF_MASK);
560
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
561
    T0 = eflags;
562
}
563

    
564
/* vm86plus version */
565
#if 0
566
void OPPROTO op_movl_T0_eflags_vm(void)
567
{
568
    int eflags;
569
    eflags = cc_table[CC_OP].compute_all();
570
    eflags |= (DF & DF_MASK);
571
    eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
572
    if (env->eflags & VIF_MASK)
573
        eflags |= IF_MASK;
574
    T0 = eflags;
575
}
576
#endif
577

    
578
void OPPROTO op_clc(void)
579
{
580
    int eflags;
581
    eflags = cc_table[CC_OP].compute_all();
582
    eflags &= ~CC_C;
583
    CC_SRC = eflags;
584
}
585

    
586
void OPPROTO op_stc(void)
587
{
588
    int eflags;
589
    eflags = cc_table[CC_OP].compute_all();
590
    eflags |= CC_C;
591
    CC_SRC = eflags;
592
}
593

    
594
void OPPROTO op_cmc(void)
595
{
596
    int eflags;
597
    eflags = cc_table[CC_OP].compute_all();
598
    eflags ^= CC_C;
599
    CC_SRC = eflags;
600
}
601

    
602
void OPPROTO op_salc(void)
603
{
604
    int cf;
605
    cf = cc_table[CC_OP].compute_c();
606
    EAX = (EAX & ~0xff) | ((-cf) & 0xff);
607
}
608

    
609
void OPPROTO op_fcomi_dummy(void)
610
{
611
    T0 = 0;
612
}
613

    
614
/* SSE support */
615
void OPPROTO op_com_dummy(void)
616
{
617
    T0 = 0;
618
}