Statistics
| Branch: | Revision:

root / ops_template.h @ 367e86e8

History | View | Annotate | Download (13.5 kB)

1

    
2
#define DATA_BITS (1 << (3 + SHIFT))
3
#define SHIFT_MASK (DATA_BITS - 1)
4
#define SIGN_MASK (1 << (DATA_BITS - 1))
5

    
6
#if DATA_BITS == 8
7
#define SUFFIX b
8
#define DATA_TYPE uint8_t
9
#define DATA_STYPE int8_t
10
#define DATA_MASK 0xff
11
#elif DATA_BITS == 16
12
#define SUFFIX w
13
#define DATA_TYPE uint16_t
14
#define DATA_STYPE int16_t
15
#define DATA_MASK 0xffff
16
#elif DATA_BITS == 32
17
#define SUFFIX l
18
#define DATA_TYPE uint32_t
19
#define DATA_STYPE int32_t
20
#define DATA_MASK 0xffffffff
21
#else
22
#error unhandled operand size
23
#endif
24

    
25
/* dynamic flags computation */
26

    
27
static int glue(compute_all_add, SUFFIX)(void)
28
{
29
    int cf, pf, af, zf, sf, of;
30
    int src1, src2;
31
    src1 = CC_SRC;
32
    src2 = CC_DST - CC_SRC;
33
    cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
34
    pf = parity_table[(uint8_t)CC_DST];
35
    af = (CC_DST ^ src1 ^ src2) & 0x10;
36
    zf = ((DATA_TYPE)CC_DST != 0) << 6;
37
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
38
    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
39
    return cf | pf | af | zf | sf | of;
40
}
41

    
42
static int glue(compute_c_add, SUFFIX)(void)
43
{
44
    int src1, cf;
45
    src1 = CC_SRC;
46
    cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
47
    return cf;
48
}
49

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

    
65
static int glue(compute_c_sub, SUFFIX)(void)
66
{
67
    int src1, src2, cf;
68
    src1 = CC_SRC;
69
    src2 = CC_SRC - CC_DST;
70
    cf = (DATA_TYPE)src1 < (DATA_TYPE)src1;
71
    return cf;
72
}
73

    
74
static int glue(compute_all_logic, SUFFIX)(void)
75
{
76
    int cf, pf, af, zf, sf, of;
77
    cf = 0;
78
    pf = parity_table[(uint8_t)CC_DST];
79
    af = 0;
80
    zf = ((DATA_TYPE)CC_DST != 0) << 6;
81
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
82
    of = 0;
83
    return cf | pf | af | zf | sf | of;
84
}
85

    
86
static int glue(compute_c_logic, SUFFIX)(void)
87
{
88
    return 0;
89
}
90

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

    
106
static int glue(compute_c_inc, SUFFIX)(void)
107
{
108
    return CC_SRC;
109
}
110

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

    
126
static int glue(compute_all_shl, SUFFIX)(void)
127
{
128
    int cf, pf, af, zf, sf, of;
129
    cf = CC_SRC & 1;
130
    pf = parity_table[(uint8_t)CC_DST];
131
    af = 0; /* undefined */
132
    zf = ((DATA_TYPE)CC_DST != 0) << 6;
133
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
134
    of = sf << 4; /* only meaniful for shr with count == 1 */
135
    return cf | pf | af | zf | sf | of;
136
}
137

    
138
static int glue(compute_c_shl, SUFFIX)(void)
139
{
140
    return CC_SRC & 1;
141
}
142

    
143
/* various optimized jumps cases */
144

    
145
void OPPROTO glue(op_jb_sub, SUFFIX)(void)
146
{
147
    int src1, src2;
148
    src1 = CC_SRC;
149
    src2 = CC_SRC - CC_DST;
150

    
151
    if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
152
        PC += PARAM1;
153
    else
154
        PC += PARAM2;
155
    FORCE_RET();
156
}
157

    
158
void OPPROTO glue(op_jz_sub, SUFFIX)(void)
159
{
160
    if ((DATA_TYPE)CC_DST != 0)
161
        PC += PARAM1;
162
    else
163
        PC += PARAM2;
164
    FORCE_RET();
165
}
166

    
167
void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
168
{
169
    int src1, src2;
170
    src1 = CC_SRC;
171
    src2 = CC_SRC - CC_DST;
172

    
173
    if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
174
        PC += PARAM1;
175
    else
176
        PC += PARAM2;
177
    FORCE_RET();
178
}
179

    
180
void OPPROTO glue(op_js_sub, SUFFIX)(void)
181
{
182
    if (CC_DST & SIGN_MASK)
183
        PC += PARAM1;
184
    else
185
        PC += PARAM2;
186
    FORCE_RET();
187
}
188

    
189
void OPPROTO glue(op_jl_sub, SUFFIX)(void)
190
{
191
    int src1, src2;
192
    src1 = CC_SRC;
193
    src2 = CC_SRC - CC_DST;
194

    
195
    if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
196
        PC += PARAM1;
197
    else
198
        PC += PARAM2;
199
    FORCE_RET();
200
}
201

    
202
void OPPROTO glue(op_jle_sub, SUFFIX)(void)
203
{
204
    int src1, src2;
205
    src1 = CC_SRC;
206
    src2 = CC_SRC - CC_DST;
207

    
208
    if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
209
        PC += PARAM1;
210
    else
211
        PC += PARAM2;
212
    FORCE_RET();
213
}
214

    
215
/* various optimized set cases */
216

    
217
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
218
{
219
    int src1, src2;
220
    src1 = CC_SRC;
221
    src2 = CC_SRC - CC_DST;
222

    
223
    T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
224
}
225

    
226
void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
227
{
228
    T0 = ((DATA_TYPE)CC_DST != 0);
229
}
230

    
231
void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
232
{
233
    int src1, src2;
234
    src1 = CC_SRC;
235
    src2 = CC_SRC - CC_DST;
236

    
237
    T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
238
}
239

    
240
void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
241
{
242
    T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
243
}
244

    
245
void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
246
{
247
    int src1, src2;
248
    src1 = CC_SRC;
249
    src2 = CC_SRC - CC_DST;
250

    
251
    T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
252
}
253

    
254
void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
255
{
256
    int src1, src2;
257
    src1 = CC_SRC;
258
    src2 = CC_SRC - CC_DST;
259

    
260
    T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
261
}
262

    
263
/* shifts */
264

    
265
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
266
{
267
    int count, src;
268
    count = T1 & SHIFT_MASK;
269
    if (count) {
270
        CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
271
        src = T0;
272
        T0 &= DATA_MASK;
273
        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
274
        CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
275
            (T0 & CC_C);
276
        CC_OP = CC_OP_EFLAGS;
277
    }
278
}
279

    
280
void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
281
{
282
    int count, src;
283
    count = T1 & SHIFT_MASK;
284
    if (count) {
285
        CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
286
        src = T0;
287
        T0 &= DATA_MASK;
288
        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
289
        CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
290
            ((T0 >> (DATA_BITS - 1)) & CC_C);
291
        CC_OP = CC_OP_EFLAGS;
292
    }
293
}
294

    
295
void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
296
{
297
    int count, res, eflags;
298
    unsigned int src;
299

    
300
    count = T1 & 0x1f;
301
#if DATA_BITS == 16
302
    count = rclw_table[count];
303
#elif DATA_BITS == 8
304
    count = rclb_table[count];
305
#endif
306
    if (count) {
307
        eflags = cc_table[CC_OP].compute_all();
308
        src = T0;
309
        res = (T0 << count) | ((eflags & CC_C) << (count - 1));
310
        if (count > 1)
311
            res |= T0 >> (DATA_BITS + 1 - count);
312
        T0 = res;
313
        CC_SRC = (eflags & ~(CC_C | CC_O)) |
314
            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
315
            ((src >> (DATA_BITS - count)) & CC_C);
316
        CC_OP = CC_OP_EFLAGS;
317
    }
318
}
319

    
320
void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
321
{
322
    int count, res, eflags;
323
    unsigned int src;
324

    
325
    count = T1 & 0x1f;
326
#if DATA_BITS == 16
327
    count = rclw_table[count];
328
#elif DATA_BITS == 8
329
    count = rclb_table[count];
330
#endif
331
    if (count) {
332
        eflags = cc_table[CC_OP].compute_all();
333
        src = T0;
334
        res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
335
        if (count > 1)
336
            res |= T0 << (DATA_BITS + 1 - count);
337
        T0 = res;
338
        CC_SRC = (eflags & ~(CC_C | CC_O)) |
339
            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
340
            ((src >> (count - 1)) & CC_C);
341
        CC_OP = CC_OP_EFLAGS;
342
    }
343
}
344

    
345
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
346
{
347
    int count;
348
    count = T1 & 0x1f;
349
    if (count == 1) {
350
        CC_SRC = T0;
351
        T0 = T0 << 1;
352
        CC_DST = T0;
353
        CC_OP = CC_OP_ADDB + SHIFT;
354
    } else if (count) {
355
        CC_SRC = T0 >> (DATA_BITS - count);
356
        T0 = T0 << count;
357
        CC_DST = T0;
358
        CC_OP = CC_OP_SHLB + SHIFT;
359
    }
360
}
361

    
362
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
363
{
364
    int count;
365
    count = T1 & 0x1f;
366
    if (count) {
367
        T0 &= DATA_MASK;
368
        CC_SRC = T0 >> (count - 1);
369
        T0 = T0 >> count;
370
        CC_DST = T0;
371
        CC_OP = CC_OP_SHLB + SHIFT;
372
    }
373
}
374

    
375
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
376
{
377
    int count, src;
378
    count = T1 & 0x1f;
379
    if (count) {
380
        src = (DATA_STYPE)T0;
381
        CC_SRC =  src >> (count - 1);
382
        T0 = src >> count;
383
        CC_DST = T0;
384
        CC_OP = CC_OP_SHLB + SHIFT;
385
    }
386
}
387

    
388
/* string operations */
389
/* XXX: maybe use lower level instructions to ease exception handling */
390

    
391
void OPPROTO glue(op_movs, SUFFIX)(void)
392
{
393
    int v;
394
    v = glue(ldu, SUFFIX)((void *)ESI);
395
    glue(st, SUFFIX)((void *)EDI, v);
396
    ESI += (DF << SHIFT);
397
    EDI += (DF << SHIFT);
398
}
399

    
400
void OPPROTO glue(op_rep_movs, SUFFIX)(void)
401
{
402
    int v, inc;
403
    inc = (DF << SHIFT);
404
    while (ECX != 0) {
405
        v = glue(ldu, SUFFIX)((void *)ESI);
406
        glue(st, SUFFIX)((void *)EDI, v);
407
        ESI += inc;
408
        EDI += inc;
409
        ECX--;
410
    }
411
}
412

    
413
void OPPROTO glue(op_stos, SUFFIX)(void)
414
{
415
    glue(st, SUFFIX)((void *)EDI, EAX);
416
    EDI += (DF << SHIFT);
417
}
418

    
419
void OPPROTO glue(op_rep_stos, SUFFIX)(void)
420
{
421
    int inc;
422
    inc = (DF << SHIFT);
423
    while (ECX != 0) {
424
        glue(st, SUFFIX)((void *)EDI, EAX);
425
        EDI += inc;
426
        ECX--;
427
    }
428
}
429

    
430
void OPPROTO glue(op_lods, SUFFIX)(void)
431
{
432
    int v;
433
    v = glue(ldu, SUFFIX)((void *)ESI);
434
#if SHIFT == 0
435
    EAX = (EAX & ~0xff) | v;
436
#elif SHIFT == 1
437
    EAX = (EAX & ~0xffff) | v;
438
#else
439
    EAX = v;
440
#endif
441
    ESI += (DF << SHIFT);
442
}
443

    
444
/* don't know if it is used */
445
void OPPROTO glue(op_rep_lods, SUFFIX)(void)
446
{
447
    int v, inc;
448
    inc = (DF << SHIFT);
449
    while (ECX != 0) {
450
        v = glue(ldu, SUFFIX)((void *)ESI);
451
#if SHIFT == 0
452
        EAX = (EAX & ~0xff) | v;
453
#elif SHIFT == 1
454
        EAX = (EAX & ~0xffff) | v;
455
#else
456
        EAX = v;
457
#endif
458
        ESI += inc;
459
        ECX--;
460
    }
461
}
462

    
463
void OPPROTO glue(op_scas, SUFFIX)(void)
464
{
465
    int v;
466

    
467
    v = glue(ldu, SUFFIX)((void *)ESI);
468
    ESI += (DF << SHIFT);
469
    CC_SRC = EAX;
470
    CC_DST = EAX - v;
471
}
472

    
473
void OPPROTO glue(op_repz_scas, SUFFIX)(void)
474
{
475
    int v1, v2, inc;
476

    
477
    if (ECX != 0) {
478
        /* NOTE: the flags are not modified if ECX == 0 */
479
#if SHIFT == 0
480
        v1 = EAX & 0xff;
481
#elif SHIFT == 1
482
        v1 = EAX & 0xffff;
483
#else
484
        v1 = EAX;
485
#endif
486
        inc = (DF << SHIFT);
487
        do {
488
            v2 = glue(ldu, SUFFIX)((void *)ESI);
489
            if (v1 != v2)
490
                break;
491
            ESI += inc;
492
            ECX--;
493
        } while (ECX != 0);
494
        CC_SRC = v1;
495
        CC_DST = v1 - v2;
496
        CC_OP = CC_OP_SUBB + SHIFT;
497
    }
498
}
499

    
500
void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
501
{
502
    int v1, v2, inc;
503

    
504
    if (ECX != 0) {
505
        /* NOTE: the flags are not modified if ECX == 0 */
506
#if SHIFT == 0
507
        v1 = EAX & 0xff;
508
#elif SHIFT == 1
509
        v1 = EAX & 0xffff;
510
#else
511
        v1 = EAX;
512
#endif
513
        inc = (DF << SHIFT);
514
        do {
515
            v2 = glue(ldu, SUFFIX)((void *)ESI);
516
            if (v1 == v2)
517
                break;
518
            ESI += inc;
519
            ECX--;
520
        } while (ECX != 0);
521
        CC_SRC = v1;
522
        CC_DST = v1 - v2;
523
        CC_OP = CC_OP_SUBB + SHIFT;
524
    }
525
}
526

    
527
void OPPROTO glue(op_cmps, SUFFIX)(void)
528
{
529
    int v1, v2;
530
    v1 = glue(ldu, SUFFIX)((void *)ESI);
531
    v2 = glue(ldu, SUFFIX)((void *)EDI);
532
    ESI += (DF << SHIFT);
533
    EDI += (DF << SHIFT);
534
    CC_SRC = v1;
535
    CC_DST = v1 - v2;
536
}
537

    
538
void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
539
{
540
    int v1, v2, inc;
541
    if (ECX != 0) {
542
        inc = (DF << SHIFT);
543
        do {
544
            v1 = glue(ldu, SUFFIX)((void *)ESI);
545
            v2 = glue(ldu, SUFFIX)((void *)EDI);
546
            if (v1 != v2)
547
                break;
548
            ESI += inc;
549
            EDI += inc;
550
            ECX--;
551
        } while (ECX != 0);
552
        CC_SRC = v1;
553
        CC_DST = v1 - v2;
554
        CC_OP = CC_OP_SUBB + SHIFT;
555
    }
556
}
557

    
558
void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
559
{
560
    int v1, v2, inc;
561
    if (ECX != 0) {
562
        inc = (DF << SHIFT);
563
        do {
564
            v1 = glue(ldu, SUFFIX)((void *)ESI);
565
            v2 = glue(ldu, SUFFIX)((void *)EDI);
566
            if (v1 == v2)
567
                break;
568
            ESI += inc;
569
            EDI += inc;
570
            ECX--;
571
        } while (ECX != 0);
572
        CC_SRC = v1;
573
        CC_DST = v1 - v2;
574
        CC_OP = CC_OP_SUBB + SHIFT;
575
    }
576
}
577

    
578
void OPPROTO glue(op_outs, SUFFIX)(void)
579
{
580
    int v, dx;
581
    dx = EDX & 0xffff;
582
    v = glue(ldu, SUFFIX)((void *)ESI);
583
    glue(port_out, SUFFIX)(dx, v);
584
    ESI += (DF << SHIFT);
585
}
586

    
587
void OPPROTO glue(op_rep_outs, SUFFIX)(void)
588
{
589
    int v, dx, inc;
590
    inc = (DF << SHIFT);
591
    dx = EDX & 0xffff;
592
    while (ECX != 0) {
593
        v = glue(ldu, SUFFIX)((void *)ESI);
594
        glue(port_out, SUFFIX)(dx, v);
595
        ESI += inc;
596
        ECX--;
597
    }
598
}
599

    
600
void OPPROTO glue(op_ins, SUFFIX)(void)
601
{
602
    int v, dx;
603
    dx = EDX & 0xffff;
604
    v = glue(port_in, SUFFIX)(dx);
605
    glue(st, SUFFIX)((void *)EDI, v);
606
    EDI += (DF << SHIFT);
607
}
608

    
609
void OPPROTO glue(op_rep_ins, SUFFIX)(void)
610
{
611
    int v, dx, inc;
612
    inc = (DF << SHIFT);
613
    dx = EDX & 0xffff;
614
    while (ECX != 0) {
615
        v = glue(port_in, SUFFIX)(dx);
616
        glue(st, SUFFIX)((void *)EDI, v);
617
        EDI += (DF << SHIFT);
618
        ECX--;
619
    }
620
}
621

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