Statistics
| Branch: | Revision:

root / ops_template.h @ 5132455e

History | View | Annotate | Download (19.3 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_SRC;
97
    src2 = CC_SRC - CC_DST;
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_SRC;
111
    src2 = CC_SRC - CC_DST;
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_SRC;
121
    src2 = CC_SRC - CC_DST - 1;
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_SRC;
135
    src2 = CC_SRC - CC_DST - 1;
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_SRC;
238
    src2 = CC_SRC - CC_DST;
239

    
240
    if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
241
        EIP = PARAM1;
242
    else
243
        EIP = PARAM2;
244
    FORCE_RET();
245
}
246

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

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

    
262
    if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
263
        EIP = PARAM1;
264
    else
265
        EIP = PARAM2;
266
    FORCE_RET();
267
}
268

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

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

    
284
    if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
285
        EIP = PARAM1;
286
    else
287
        EIP = PARAM2;
288
    FORCE_RET();
289
}
290

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

    
297
    if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
298
        EIP = PARAM1;
299
    else
300
        EIP = PARAM2;
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_SRC;
365
    src2 = CC_SRC - CC_DST;
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_SRC;
379
    src2 = CC_SRC - CC_DST;
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_SRC;
393
    src2 = CC_SRC - CC_DST;
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_SRC;
402
    src2 = CC_SRC - CC_DST;
403

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

    
407
/* shifts */
408

    
409
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
410
{
411
    int count, src;
412
    count = T1 & SHIFT_MASK;
413
    if (count) {
414
        CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
415
        src = T0;
416
        T0 &= DATA_MASK;
417
        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
418
        CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
419
            (T0 & CC_C);
420
        CC_OP = CC_OP_EFLAGS;
421
    }
422
    FORCE_RET();
423
}
424

    
425
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void)
426
{
427
    int count;
428
    count = T1 & SHIFT_MASK;
429
    if (count) {
430
        T0 &= DATA_MASK;
431
        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
432
    }
433
    FORCE_RET();
434
}
435

    
436
void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
437
{
438
    int count, src;
439
    count = T1 & SHIFT_MASK;
440
    if (count) {
441
        CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
442
        src = T0;
443
        T0 &= DATA_MASK;
444
        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
445
        CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
446
            ((T0 >> (DATA_BITS - 1)) & CC_C);
447
        CC_OP = CC_OP_EFLAGS;
448
    }
449
    FORCE_RET();
450
}
451

    
452
void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void)
453
{
454
    int count;
455
    count = T1 & SHIFT_MASK;
456
    if (count) {
457
        T0 &= DATA_MASK;
458
        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
459
    }
460
    FORCE_RET();
461
}
462

    
463
void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
464
{
465
    int count, res, eflags;
466
    unsigned int src;
467

    
468
    count = T1 & 0x1f;
469
#if DATA_BITS == 16
470
    count = rclw_table[count];
471
#elif DATA_BITS == 8
472
    count = rclb_table[count];
473
#endif
474
    if (count) {
475
        eflags = cc_table[CC_OP].compute_all();
476
        T0 &= DATA_MASK;
477
        src = T0;
478
        res = (T0 << count) | ((eflags & CC_C) << (count - 1));
479
        if (count > 1)
480
            res |= T0 >> (DATA_BITS + 1 - count);
481
        T0 = res;
482
        CC_SRC = (eflags & ~(CC_C | CC_O)) |
483
            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
484
            ((src >> (DATA_BITS - count)) & CC_C);
485
        CC_OP = CC_OP_EFLAGS;
486
    }
487
    FORCE_RET();
488
}
489

    
490
void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
491
{
492
    int count, res, eflags;
493
    unsigned int src;
494

    
495
    count = T1 & 0x1f;
496
#if DATA_BITS == 16
497
    count = rclw_table[count];
498
#elif DATA_BITS == 8
499
    count = rclb_table[count];
500
#endif
501
    if (count) {
502
        eflags = cc_table[CC_OP].compute_all();
503
        T0 &= DATA_MASK;
504
        src = T0;
505
        res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
506
        if (count > 1)
507
            res |= T0 << (DATA_BITS + 1 - count);
508
        T0 = res;
509
        CC_SRC = (eflags & ~(CC_C | CC_O)) |
510
            (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | 
511
            ((src >> (count - 1)) & CC_C);
512
        CC_OP = CC_OP_EFLAGS;
513
    }
514
    FORCE_RET();
515
}
516

    
517
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
518
{
519
    int count;
520
    count = T1 & 0x1f;
521
    if (count) {
522
        CC_SRC = (DATA_TYPE)T0 << (count - 1);
523
        T0 = T0 << count;
524
        CC_DST = T0;
525
        CC_OP = CC_OP_SHLB + SHIFT;
526
    }
527
    FORCE_RET();
528
}
529

    
530
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
531
{
532
    int count;
533
    count = T1 & 0x1f;
534
    T0 = T0 << count;
535
    FORCE_RET();
536
}
537

    
538
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
539
{
540
    int count;
541
    count = T1 & 0x1f;
542
    if (count) {
543
        T0 &= DATA_MASK;
544
        CC_SRC = T0 >> (count - 1);
545
        T0 = T0 >> count;
546
        CC_DST = T0;
547
        CC_OP = CC_OP_SARB + SHIFT;
548
    }
549
    FORCE_RET();
550
}
551

    
552
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
553
{
554
    int count;
555
    count = T1 & 0x1f;
556
    T0 &= DATA_MASK;
557
    T0 = T0 >> count;
558
    FORCE_RET();
559
}
560

    
561
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
562
{
563
    int count, src;
564
    count = T1 & 0x1f;
565
    if (count) {
566
        src = (DATA_STYPE)T0;
567
        CC_SRC = src >> (count - 1);
568
        T0 = src >> count;
569
        CC_DST = T0;
570
        CC_OP = CC_OP_SARB + SHIFT;
571
    }
572
    FORCE_RET();
573
}
574

    
575
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
576
{
577
    int count, src;
578
    count = T1 & 0x1f;
579
    src = (DATA_STYPE)T0;
580
    T0 = src >> count;
581
    FORCE_RET();
582
}
583

    
584
#if DATA_BITS == 16
585
/* XXX: overflow flag might be incorrect in some cases in shldw */
586
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
587
{
588
    int count;
589
    unsigned int res;
590
    count = PARAM1;
591
    T1 &= 0xffff;
592
    res = T1 | (T0 << 16);
593
    CC_SRC = res >> (32 - count);
594
    res <<= count;
595
    if (count > 16)
596
        res |= T1 << (count - 16);
597
    T0 = res >> 16;
598
    CC_DST = T0;
599
}
600

    
601
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
602
{
603
    int count;
604
    unsigned int res;
605
    count = ECX & 0x1f;
606
    if (count) {
607
        T1 &= 0xffff;
608
        res = T1 | (T0 << 16);
609
        CC_SRC = res >> (32 - count);
610
        res <<= count;
611
        if (count > 16)
612
          res |= T1 << (count - 16);
613
        T0 = res >> 16;
614
        CC_DST = T0;
615
        CC_OP = CC_OP_SARB + SHIFT;
616
    }
617
    FORCE_RET();
618
}
619

    
620
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
621
{
622
    int count;
623
    unsigned int res;
624

    
625
    count = PARAM1;
626
    res = (T0 & 0xffff) | (T1 << 16);
627
    CC_SRC = res >> (count - 1);
628
    res >>= count;
629
    if (count > 16)
630
        res |= T1 << (32 - count);
631
    T0 = res;
632
    CC_DST = T0;
633
}
634

    
635

    
636
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
637
{
638
    int count;
639
    unsigned int res;
640

    
641
    count = ECX & 0x1f;
642
    if (count) {
643
        res = (T0 & 0xffff) | (T1 << 16);
644
        CC_SRC = res >> (count - 1);
645
        res >>= count;
646
        if (count > 16)
647
            res |= T1 << (32 - count);
648
        T0 = res;
649
        CC_DST = T0;
650
        CC_OP = CC_OP_SARB + SHIFT;
651
    }
652
    FORCE_RET();
653
}
654
#endif
655

    
656
#if DATA_BITS == 32
657
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
658
{
659
    int count;
660
    count = PARAM1;
661
    T0 &= DATA_MASK;
662
    T1 &= DATA_MASK;
663
    CC_SRC = T0 << (count - 1);
664
    T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
665
    CC_DST = T0;
666
}
667

    
668
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
669
{
670
    int count;
671
    count = ECX & 0x1f;
672
    if (count) {
673
        T0 &= DATA_MASK;
674
        T1 &= DATA_MASK;
675
        CC_SRC = T0 << (count - 1);
676
        T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
677
        CC_DST = T0;
678
        CC_OP = CC_OP_SHLB + SHIFT;
679
    }
680
    FORCE_RET();
681
}
682

    
683
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
684
{
685
    int count;
686
    count = PARAM1;
687
    T0 &= DATA_MASK;
688
    T1 &= DATA_MASK;
689
    CC_SRC = T0 >> (count - 1);
690
    T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
691
    CC_DST = T0;
692
}
693

    
694

    
695
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
696
{
697
    int count;
698
    count = ECX & 0x1f;
699
    if (count) {
700
        T0 &= DATA_MASK;
701
        T1 &= DATA_MASK;
702
        CC_SRC = T0 >> (count - 1);
703
        T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
704
        CC_DST = T0;
705
        CC_OP = CC_OP_SARB + SHIFT;
706
    }
707
    FORCE_RET();
708
}
709
#endif
710

    
711
/* carry add/sub (we only need to set CC_OP differently) */
712

    
713
void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
714
{
715
    int cf;
716
    cf = cc_table[CC_OP].compute_c();
717
    CC_SRC = T0;
718
    T0 = T0 + T1 + cf;
719
    CC_DST = T0;
720
    CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
721
}
722

    
723
void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
724
{
725
    int cf;
726
    cf = cc_table[CC_OP].compute_c();
727
    CC_SRC = T0;
728
    T0 = T0 - T1 - cf;
729
    CC_DST = T0;
730
    CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
731
}
732

    
733
void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
734
{
735
    CC_SRC = EAX;
736
    CC_DST = EAX - T0;
737
    if ((DATA_TYPE)CC_DST == 0) {
738
        T0 = T1;
739
    } else {
740
        EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
741
    }
742
    FORCE_RET();
743
}
744

    
745
/* bit operations */
746
#if DATA_BITS >= 16
747

    
748
void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
749
{
750
    int count;
751
    count = T1 & SHIFT_MASK;
752
    CC_SRC = T0 >> count;
753
}
754

    
755
void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
756
{
757
    int count;
758
    count = T1 & SHIFT_MASK;
759
    CC_SRC = T0 >> count;
760
    T0 |= (1 << count);
761
}
762

    
763
void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
764
{
765
    int count;
766
    count = T1 & SHIFT_MASK;
767
    CC_SRC = T0 >> count;
768
    T0 &= ~(1 << count);
769
}
770

    
771
void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
772
{
773
    int count;
774
    count = T1 & SHIFT_MASK;
775
    CC_SRC = T0 >> count;
776
    T0 ^= (1 << count);
777
}
778

    
779
void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
780
{
781
    int res, count;
782
    res = T0 & DATA_MASK;
783
    if (res != 0) {
784
        count = 0;
785
        while ((res & 1) == 0) {
786
            count++;
787
            res >>= 1;
788
        }
789
        T0 = count;
790
        CC_DST = 1; /* ZF = 1 */
791
    } else {
792
        CC_DST = 0; /* ZF = 1 */
793
    }
794
    FORCE_RET();
795
}
796

    
797
void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
798
{
799
    int res, count;
800
    res = T0 & DATA_MASK;
801
    if (res != 0) {
802
        count = DATA_BITS - 1;
803
        while ((res & SIGN_MASK) == 0) {
804
            count--;
805
            res <<= 1;
806
        }
807
        T0 = count;
808
        CC_DST = 1; /* ZF = 1 */
809
    } else {
810
        CC_DST = 0; /* ZF = 1 */
811
    }
812
    FORCE_RET();
813
}
814

    
815
#endif
816

    
817
/* string operations */
818
/* XXX: maybe use lower level instructions to ease 16 bit / segment handling */
819

    
820
#define STRING_SUFFIX _fast
821
#define SI_ADDR (void *)ESI
822
#define DI_ADDR (void *)EDI
823
#define INC_SI() ESI += inc
824
#define INC_DI() EDI += inc
825
#define CX ECX
826
#define DEC_CX() ECX--
827
#include "op_string.h"
828

    
829
#define STRING_SUFFIX _a32
830
#define SI_ADDR (uint8_t *)A0 + ESI
831
#define DI_ADDR env->seg_cache[R_ES].base + EDI
832
#define INC_SI() ESI += inc
833
#define INC_DI() EDI += inc
834
#define CX ECX
835
#define DEC_CX() ECX--
836
#include "op_string.h"
837

    
838
#define STRING_SUFFIX _a16
839
#define SI_ADDR (uint8_t *)A0 + (ESI & 0xffff)
840
#define DI_ADDR env->seg_cache[R_ES].base + (EDI & 0xffff)
841
#define INC_SI() ESI = (ESI & ~0xffff) | ((ESI + inc) & 0xffff)
842
#define INC_DI() EDI = (EDI & ~0xffff) | ((EDI + inc) & 0xffff)
843
#define CX (ECX & 0xffff)
844
#define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
845
#include "op_string.h"
846

    
847
/* port I/O */
848

    
849
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
850
{
851
    glue(cpu_x86_out, SUFFIX)(env, T0 & 0xffff, T1 & DATA_MASK);
852
}
853

    
854
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
855
{
856
    T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff);
857
}
858

    
859
#undef DATA_BITS
860
#undef SHIFT_MASK
861
#undef SIGN_MASK
862
#undef DATA_TYPE
863
#undef DATA_STYPE
864
#undef DATA_MASK
865
#undef SUFFIX