Statistics
| Branch: | Revision:

root / target-i386 / ops_template.h @ 3e25f951

History | View | Annotate | Download (13.9 kB)

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

    
25
#if DATA_BITS == 8
26
#define SUFFIX b
27
#define DATA_TYPE uint8_t
28
#define DATA_STYPE int8_t
29
#define DATA_MASK 0xff
30
#elif DATA_BITS == 16
31
#define SUFFIX w
32
#define DATA_TYPE uint16_t
33
#define DATA_STYPE int16_t
34
#define DATA_MASK 0xffff
35
#elif DATA_BITS == 32
36
#define SUFFIX l
37
#define DATA_TYPE uint32_t
38
#define DATA_STYPE int32_t
39
#define DATA_MASK 0xffffffff
40
#else
41
#error unhandled operand size
42
#endif
43

    
44
/* dynamic flags computation */
45

    
46
static int glue(compute_all_add, SUFFIX)(void)
47
{
48
    int cf, pf, af, zf, sf, of;
49
    int src1, src2;
50
    src1 = CC_SRC;
51
    src2 = CC_DST - CC_SRC;
52
    cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
53
    pf = parity_table[(uint8_t)CC_DST];
54
    af = (CC_DST ^ src1 ^ src2) & 0x10;
55
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
56
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
57
    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
58
    return cf | pf | af | zf | sf | of;
59
}
60

    
61
static int glue(compute_c_add, SUFFIX)(void)
62
{
63
    int src1, cf;
64
    src1 = CC_SRC;
65
    cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
66
    return cf;
67
}
68

    
69
static int glue(compute_all_adc, SUFFIX)(void)
70
{
71
    int cf, pf, af, zf, sf, of;
72
    int src1, src2;
73
    src1 = CC_SRC;
74
    src2 = CC_DST - CC_SRC - 1;
75
    cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
76
    pf = parity_table[(uint8_t)CC_DST];
77
    af = (CC_DST ^ src1 ^ src2) & 0x10;
78
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
79
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
80
    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
81
    return cf | pf | af | zf | sf | of;
82
}
83

    
84
static int glue(compute_c_adc, SUFFIX)(void)
85
{
86
    int src1, cf;
87
    src1 = CC_SRC;
88
    cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
89
    return cf;
90
}
91

    
92
static int glue(compute_all_sub, SUFFIX)(void)
93
{
94
    int cf, pf, af, zf, sf, of;
95
    int src1, src2;
96
    src1 = CC_DST + CC_SRC;
97
    src2 = CC_SRC;
98
    cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
99
    pf = parity_table[(uint8_t)CC_DST];
100
    af = (CC_DST ^ src1 ^ src2) & 0x10;
101
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
102
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
103
    of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
104
    return cf | pf | af | zf | sf | of;
105
}
106

    
107
static int glue(compute_c_sub, SUFFIX)(void)
108
{
109
    int src1, src2, cf;
110
    src1 = CC_DST + CC_SRC;
111
    src2 = CC_SRC;
112
    cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
113
    return cf;
114
}
115

    
116
static int glue(compute_all_sbb, SUFFIX)(void)
117
{
118
    int cf, pf, af, zf, sf, of;
119
    int src1, src2;
120
    src1 = CC_DST + CC_SRC + 1;
121
    src2 = CC_SRC;
122
    cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
123
    pf = parity_table[(uint8_t)CC_DST];
124
    af = (CC_DST ^ src1 ^ src2) & 0x10;
125
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
126
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
127
    of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
128
    return cf | pf | af | zf | sf | of;
129
}
130

    
131
static int glue(compute_c_sbb, SUFFIX)(void)
132
{
133
    int src1, src2, cf;
134
    src1 = CC_DST + CC_SRC + 1;
135
    src2 = CC_SRC;
136
    cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
137
    return cf;
138
}
139

    
140
static int glue(compute_all_logic, SUFFIX)(void)
141
{
142
    int cf, pf, af, zf, sf, of;
143
    cf = 0;
144
    pf = parity_table[(uint8_t)CC_DST];
145
    af = 0;
146
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
147
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
148
    of = 0;
149
    return cf | pf | af | zf | sf | of;
150
}
151

    
152
static int glue(compute_c_logic, SUFFIX)(void)
153
{
154
    return 0;
155
}
156

    
157
static int glue(compute_all_inc, SUFFIX)(void)
158
{
159
    int cf, pf, af, zf, sf, of;
160
    int src1, src2;
161
    src1 = CC_DST - 1;
162
    src2 = 1;
163
    cf = CC_SRC;
164
    pf = parity_table[(uint8_t)CC_DST];
165
    af = (CC_DST ^ src1 ^ src2) & 0x10;
166
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
167
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
168
    of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
169
    return cf | pf | af | zf | sf | of;
170
}
171

    
172
#if DATA_BITS == 32
173
static int glue(compute_c_inc, SUFFIX)(void)
174
{
175
    return CC_SRC;
176
}
177
#endif
178

    
179
static int glue(compute_all_dec, SUFFIX)(void)
180
{
181
    int cf, pf, af, zf, sf, of;
182
    int src1, src2;
183
    src1 = CC_DST + 1;
184
    src2 = 1;
185
    cf = CC_SRC;
186
    pf = parity_table[(uint8_t)CC_DST];
187
    af = (CC_DST ^ src1 ^ src2) & 0x10;
188
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
189
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
190
    of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11;
191
    return cf | pf | af | zf | sf | of;
192
}
193

    
194
static int glue(compute_all_shl, SUFFIX)(void)
195
{
196
    int cf, pf, af, zf, sf, of;
197
    cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
198
    pf = parity_table[(uint8_t)CC_DST];
199
    af = 0; /* undefined */
200
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
201
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
202
    /* of is defined if shift count == 1 */
203
    of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
204
    return cf | pf | af | zf | sf | of;
205
}
206

    
207
static int glue(compute_c_shl, SUFFIX)(void)
208
{
209
    return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
210
}
211

    
212
#if DATA_BITS == 32
213
static int glue(compute_c_sar, SUFFIX)(void)
214
{
215
    return CC_SRC & 1;
216
}
217
#endif
218

    
219
static int glue(compute_all_sar, SUFFIX)(void)
220
{
221
    int cf, pf, af, zf, sf, of;
222
    cf = CC_SRC & 1;
223
    pf = parity_table[(uint8_t)CC_DST];
224
    af = 0; /* undefined */
225
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
226
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
227
    /* of is defined if shift count == 1 */
228
    of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; 
229
    return cf | pf | af | zf | sf | of;
230
}
231

    
232
/* various optimized jumps cases */
233

    
234
void OPPROTO glue(op_jb_sub, SUFFIX)(void)
235
{
236
    int src1, src2;
237
    src1 = CC_DST + CC_SRC;
238
    src2 = CC_SRC;
239

    
240
    if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
241
        JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 0, PARAM2);
242
    else
243
        JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 1, PARAM3);
244
    FORCE_RET();
245
}
246

    
247
void OPPROTO glue(op_jz_sub, SUFFIX)(void)
248
{
249
    if ((DATA_TYPE)CC_DST == 0)
250
        JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 0, PARAM2);
251
    else
252
        JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 1, PARAM3);
253
    FORCE_RET();
254
}
255

    
256
void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
257
{
258
    int src1, src2;
259
    src1 = CC_DST + CC_SRC;
260
    src2 = CC_SRC;
261

    
262
    if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
263
        JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 0, PARAM2);
264
    else
265
        JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 1, PARAM3);
266
    FORCE_RET();
267
}
268

    
269
void OPPROTO glue(op_js_sub, SUFFIX)(void)
270
{
271
    if (CC_DST & SIGN_MASK)
272
        JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 0, PARAM2);
273
    else
274
        JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 1, PARAM3);
275
    FORCE_RET();
276
}
277

    
278
void OPPROTO glue(op_jl_sub, SUFFIX)(void)
279
{
280
    int src1, src2;
281
    src1 = CC_DST + CC_SRC;
282
    src2 = CC_SRC;
283

    
284
    if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
285
        JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 0, PARAM2);
286
    else
287
        JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 1, PARAM3);
288
    FORCE_RET();
289
}
290

    
291
void OPPROTO glue(op_jle_sub, SUFFIX)(void)
292
{
293
    int src1, src2;
294
    src1 = CC_DST + CC_SRC;
295
    src2 = CC_SRC;
296

    
297
    if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
298
        JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 0, PARAM2);
299
    else
300
        JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 1, PARAM3);
301
    FORCE_RET();
302
}
303

    
304
/* oldies */
305

    
306
#if DATA_BITS >= 16
307

    
308
void OPPROTO glue(op_loopnz, SUFFIX)(void)
309
{
310
    unsigned int tmp;
311
    int eflags;
312
    eflags = cc_table[CC_OP].compute_all();
313
    tmp = (ECX - 1) & DATA_MASK;
314
    ECX = (ECX & ~DATA_MASK) | tmp;
315
    if (tmp != 0 && !(eflags & CC_Z))
316
        EIP = PARAM1;
317
    else
318
        EIP = PARAM2;
319
    FORCE_RET();
320
}
321

    
322
void OPPROTO glue(op_loopz, SUFFIX)(void)
323
{
324
    unsigned int tmp;
325
    int eflags;
326
    eflags = cc_table[CC_OP].compute_all();
327
    tmp = (ECX - 1) & DATA_MASK;
328
    ECX = (ECX & ~DATA_MASK) | tmp;
329
    if (tmp != 0 && (eflags & CC_Z))
330
        EIP = PARAM1;
331
    else
332
        EIP = PARAM2;
333
    FORCE_RET();
334
}
335

    
336
void OPPROTO glue(op_loop, SUFFIX)(void)
337
{
338
    unsigned int tmp;
339
    tmp = (ECX - 1) & DATA_MASK;
340
    ECX = (ECX & ~DATA_MASK) | tmp;
341
    if (tmp != 0)
342
        EIP = PARAM1;
343
    else
344
        EIP = PARAM2;
345
    FORCE_RET();
346
}
347

    
348
void OPPROTO glue(op_jecxz, SUFFIX)(void)
349
{
350
    if ((DATA_TYPE)ECX == 0)
351
        EIP = PARAM1;
352
    else
353
        EIP = PARAM2;
354
    FORCE_RET();
355
}
356

    
357
#endif
358

    
359
/* various optimized set cases */
360

    
361
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
362
{
363
    int src1, src2;
364
    src1 = CC_DST + CC_SRC;
365
    src2 = CC_SRC;
366

    
367
    T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
368
}
369

    
370
void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
371
{
372
    T0 = ((DATA_TYPE)CC_DST == 0);
373
}
374

    
375
void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
376
{
377
    int src1, src2;
378
    src1 = CC_DST + CC_SRC;
379
    src2 = CC_SRC;
380

    
381
    T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
382
}
383

    
384
void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
385
{
386
    T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
387
}
388

    
389
void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
390
{
391
    int src1, src2;
392
    src1 = CC_DST + CC_SRC;
393
    src2 = CC_SRC;
394

    
395
    T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
396
}
397

    
398
void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
399
{
400
    int src1, src2;
401
    src1 = CC_DST + CC_SRC;
402
    src2 = CC_SRC;
403

    
404
    T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
405
}
406

    
407
/* shifts */
408

    
409
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
410
{
411
    int count;
412
    count = T1 & 0x1f;
413
    T0 = T0 << count;
414
    FORCE_RET();
415
}
416

    
417
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
418
{
419
    int count;
420
    count = T1 & 0x1f;
421
    T0 &= DATA_MASK;
422
    T0 = T0 >> count;
423
    FORCE_RET();
424
}
425

    
426
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
427
{
428
    int count, src;
429
    count = T1 & 0x1f;
430
    src = (DATA_STYPE)T0;
431
    T0 = src >> count;
432
    FORCE_RET();
433
}
434

    
435
#undef MEM_WRITE
436
#include "ops_template_mem.h"
437

    
438
#define MEM_WRITE
439
#include "ops_template_mem.h"
440

    
441
/* bit operations */
442
#if DATA_BITS >= 16
443

    
444
void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
445
{
446
    int count;
447
    count = T1 & SHIFT_MASK;
448
    CC_SRC = T0 >> count;
449
}
450

    
451
void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
452
{
453
    int count;
454
    count = T1 & SHIFT_MASK;
455
    T1 = T0 >> count;
456
    T0 |= (1 << count);
457
}
458

    
459
void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
460
{
461
    int count;
462
    count = T1 & SHIFT_MASK;
463
    T1 = T0 >> count;
464
    T0 &= ~(1 << count);
465
}
466

    
467
void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
468
{
469
    int count;
470
    count = T1 & SHIFT_MASK;
471
    T1 = T0 >> count;
472
    T0 ^= (1 << count);
473
}
474

    
475
void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
476
{
477
    int res, count;
478
    res = T0 & DATA_MASK;
479
    if (res != 0) {
480
        count = 0;
481
        while ((res & 1) == 0) {
482
            count++;
483
            res >>= 1;
484
        }
485
        T0 = count;
486
        CC_DST = 1; /* ZF = 1 */
487
    } else {
488
        CC_DST = 0; /* ZF = 1 */
489
    }
490
    FORCE_RET();
491
}
492

    
493
void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
494
{
495
    int res, count;
496
    res = T0 & DATA_MASK;
497
    if (res != 0) {
498
        count = DATA_BITS - 1;
499
        while ((res & SIGN_MASK) == 0) {
500
            count--;
501
            res <<= 1;
502
        }
503
        T0 = count;
504
        CC_DST = 1; /* ZF = 1 */
505
    } else {
506
        CC_DST = 0; /* ZF = 1 */
507
    }
508
    FORCE_RET();
509
}
510

    
511
#endif
512

    
513
#if DATA_BITS == 32
514
void OPPROTO op_update_bt_cc(void)
515
{
516
    CC_SRC = T1;
517
}
518
#endif
519

    
520
/* string operations */
521

    
522
void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
523
{
524
    T0 = DF << SHIFT;
525
}
526

    
527
void OPPROTO glue(op_string_jz_sub, SUFFIX)(void)
528
{
529
    if ((DATA_TYPE)CC_DST == 0)
530
        JUMP_TB2(glue(op_string_jz_sub, SUFFIX), PARAM1, 1);
531
    FORCE_RET();
532
}
533

    
534
void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void)
535
{
536
    if ((DATA_TYPE)CC_DST != 0)
537
        JUMP_TB2(glue(op_string_jnz_sub, SUFFIX), PARAM1, 1);
538
    FORCE_RET();
539
}
540

    
541
void OPPROTO glue(glue(op_string_jz_sub, SUFFIX), _im)(void)
542
{
543
    if ((DATA_TYPE)CC_DST == 0) {
544
        EIP = PARAM1;
545
        if (env->eflags & TF_MASK) {
546
            raise_exception(EXCP01_SSTP);
547
        }
548
        T0 = 0;
549
        EXIT_TB();
550
    }
551
    FORCE_RET();
552
}
553

    
554
void OPPROTO glue(glue(op_string_jnz_sub, SUFFIX), _im)(void)
555
{
556
    if ((DATA_TYPE)CC_DST != 0) {
557
        EIP = PARAM1;
558
        if (env->eflags & TF_MASK) {
559
            raise_exception(EXCP01_SSTP);
560
        }
561
        T0 = 0;
562
        EXIT_TB();
563
    }
564
    FORCE_RET();
565
}
566

    
567
#if DATA_BITS >= 16
568
void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
569
{
570
    if ((DATA_TYPE)ECX == 0)
571
        JUMP_TB(glue(op_jz_ecx, SUFFIX), PARAM1, 1, PARAM2);
572
    FORCE_RET();
573
}
574

    
575
void OPPROTO glue(glue(op_jz_ecx, SUFFIX), _im)(void)
576
{
577
    if ((DATA_TYPE)ECX == 0) {
578
        EIP = PARAM1;
579
        if (env->eflags & TF_MASK) {
580
            raise_exception(EXCP01_SSTP);
581
        }
582
        T0 = 0;
583
        EXIT_TB();
584
    }
585
    FORCE_RET();
586
}
587
#endif
588

    
589
/* port I/O */
590

    
591
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
592
{
593
    glue(cpu_x86_out, SUFFIX)(env, T0 & 0xffff, T1 & DATA_MASK);
594
}
595

    
596
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
597
{
598
    T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff);
599
}
600

    
601
void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
602
{
603
    T0 = glue(cpu_x86_in, SUFFIX)(env, EDX & 0xffff);
604
}
605

    
606
void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
607
{
608
    glue(cpu_x86_out, SUFFIX)(env, EDX & 0xffff, T0);
609
}
610

    
611
void OPPROTO glue(glue(op_check_io, SUFFIX), _T0)(void)
612
{
613
    glue(glue(check_io, SUFFIX), _T0)();
614
}
615

    
616
void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void)
617
{
618
    glue(glue(check_io, SUFFIX), _DX)();
619
}
620

    
621
#undef DATA_BITS
622
#undef SHIFT_MASK
623
#undef SIGN_MASK
624
#undef DATA_TYPE
625
#undef DATA_STYPE
626
#undef DATA_MASK
627
#undef SUFFIX