Statistics
| Branch: | Revision:

root / ops_template.h @ d691f669

History | View | Annotate | Download (23 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
#if DATA_BITS == 32
208
static int glue(compute_c_shl, SUFFIX)(void)
209
{
210
    return CC_SRC & 1;
211
}
212
#endif
213

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

    
227
/* various optimized jumps cases */
228

    
229
void OPPROTO glue(op_jb_sub, SUFFIX)(void)
230
{
231
    int src1, src2;
232
    src1 = CC_SRC;
233
    src2 = CC_SRC - CC_DST;
234

    
235
    if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
236
        EIP = PARAM1;
237
    else
238
        EIP = PARAM2;
239
    FORCE_RET();
240
}
241

    
242
void OPPROTO glue(op_jz_sub, SUFFIX)(void)
243
{
244
    if ((DATA_TYPE)CC_DST == 0)
245
        EIP = PARAM1;
246
    else
247
        EIP = PARAM2;
248
    FORCE_RET();
249
}
250

    
251
void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
252
{
253
    int src1, src2;
254
    src1 = CC_SRC;
255
    src2 = CC_SRC - CC_DST;
256

    
257
    if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
258
        EIP = PARAM1;
259
    else
260
        EIP = PARAM2;
261
    FORCE_RET();
262
}
263

    
264
void OPPROTO glue(op_js_sub, SUFFIX)(void)
265
{
266
    if (CC_DST & SIGN_MASK)
267
        EIP = PARAM1;
268
    else
269
        EIP = PARAM2;
270
    FORCE_RET();
271
}
272

    
273
void OPPROTO glue(op_jl_sub, SUFFIX)(void)
274
{
275
    int src1, src2;
276
    src1 = CC_SRC;
277
    src2 = CC_SRC - CC_DST;
278

    
279
    if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
280
        EIP = PARAM1;
281
    else
282
        EIP = PARAM2;
283
    FORCE_RET();
284
}
285

    
286
void OPPROTO glue(op_jle_sub, SUFFIX)(void)
287
{
288
    int src1, src2;
289
    src1 = CC_SRC;
290
    src2 = CC_SRC - CC_DST;
291

    
292
    if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
293
        EIP = PARAM1;
294
    else
295
        EIP = PARAM2;
296
    FORCE_RET();
297
}
298

    
299
/* oldies */
300

    
301
#if DATA_BITS >= 16
302

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

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

    
331
void OPPROTO glue(op_loop, SUFFIX)(void)
332
{
333
    unsigned int tmp;
334
    tmp = (ECX - 1) & DATA_MASK;
335
    ECX = (ECX & ~DATA_MASK) | tmp;
336
    if (tmp != 0)
337
        EIP = PARAM1;
338
    else
339
        EIP = PARAM2;
340
    FORCE_RET();
341
}
342

    
343
void OPPROTO glue(op_jecxz, SUFFIX)(void)
344
{
345
    if ((DATA_TYPE)ECX == 0)
346
        EIP = PARAM1;
347
    else
348
        EIP = PARAM2;
349
    FORCE_RET();
350
}
351

    
352
#endif
353

    
354
/* various optimized set cases */
355

    
356
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
357
{
358
    int src1, src2;
359
    src1 = CC_SRC;
360
    src2 = CC_SRC - CC_DST;
361

    
362
    T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
363
}
364

    
365
void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
366
{
367
    T0 = ((DATA_TYPE)CC_DST == 0);
368
}
369

    
370
void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
371
{
372
    int src1, src2;
373
    src1 = CC_SRC;
374
    src2 = CC_SRC - CC_DST;
375

    
376
    T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
377
}
378

    
379
void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
380
{
381
    T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
382
}
383

    
384
void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
385
{
386
    int src1, src2;
387
    src1 = CC_SRC;
388
    src2 = CC_SRC - CC_DST;
389

    
390
    T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
391
}
392

    
393
void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
394
{
395
    int src1, src2;
396
    src1 = CC_SRC;
397
    src2 = CC_SRC - CC_DST;
398

    
399
    T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
400
}
401

    
402
/* shifts */
403

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

    
420
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void)
421
{
422
    int count;
423
    count = T1 & SHIFT_MASK;
424
    if (count) {
425
        T0 &= DATA_MASK;
426
        T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
427
    }
428
    FORCE_RET();
429
}
430

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

    
447
void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void)
448
{
449
    int count;
450
    count = T1 & SHIFT_MASK;
451
    if (count) {
452
        T0 &= DATA_MASK;
453
        T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
454
    }
455
    FORCE_RET();
456
}
457

    
458
void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
459
{
460
    int count, res, eflags;
461
    unsigned int src;
462

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

    
485
void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
486
{
487
    int count, res, eflags;
488
    unsigned int src;
489

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

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

    
525
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
526
{
527
    int count;
528
    count = T1 & 0x1f;
529
    T0 = T0 << count;
530
    FORCE_RET();
531
}
532

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

    
547
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
548
{
549
    int count;
550
    count = T1 & 0x1f;
551
    T0 &= DATA_MASK;
552
    T0 = T0 >> count;
553
    FORCE_RET();
554
}
555

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

    
570
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
571
{
572
    int count, src;
573
    count = T1 & 0x1f;
574
    src = (DATA_STYPE)T0;
575
    T0 = src >> count;
576
    FORCE_RET();
577
}
578

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

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

    
614
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
615
{
616
    int count;
617
    unsigned int res;
618

    
619
    count = PARAM1;
620
    res = (T0 & 0xffff) | (T1 << 16);
621
    CC_SRC = res >> (count - 1);
622
    res >>= count;
623
    if (count > 16)
624
        res |= T1 << (32 - count);
625
    T0 = res;
626
    CC_DST = T0;
627
}
628

    
629

    
630
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
631
{
632
    int count;
633
    unsigned int res;
634

    
635
    count = ECX & 0x1f;
636
    if (count) {
637
        res = (T0 & 0xffff) | (T1 << 16);
638
        CC_SRC = res >> (count - 1);
639
        res >>= count;
640
        if (count > 16)
641
            res |= T1 << (32 - count);
642
        T0 = res;
643
        CC_DST = T0;
644
        CC_OP = CC_OP_SARB + SHIFT;
645
    }
646
}
647
#endif
648

    
649
#if DATA_BITS == 32
650
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
651
{
652
    int count;
653
    count = PARAM1;
654
    T0 &= DATA_MASK;
655
    T1 &= DATA_MASK;
656
    CC_SRC = T0 << (count - 1);
657
    T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
658
    CC_DST = T0;
659
}
660

    
661
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
662
{
663
    int count;
664
    count = ECX & 0x1f;
665
    if (count) {
666
        T0 &= DATA_MASK;
667
        T1 &= DATA_MASK;
668
        CC_SRC = T0 << (count - 1);
669
        T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
670
        CC_DST = T0;
671
        CC_OP = CC_OP_SHLB + SHIFT;
672
    }
673
}
674

    
675
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
676
{
677
    int count;
678
    count = PARAM1;
679
    T0 &= DATA_MASK;
680
    T1 &= DATA_MASK;
681
    CC_SRC = T0 >> (count - 1);
682
    T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
683
    CC_DST = T0;
684
}
685

    
686

    
687
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
688
{
689
    int count;
690
    count = ECX & 0x1f;
691
    if (count) {
692
        T0 &= DATA_MASK;
693
        T1 &= DATA_MASK;
694
        CC_SRC = T0 >> (count - 1);
695
        T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
696
        CC_DST = T0;
697
        CC_OP = CC_OP_SARB + SHIFT;
698
    }
699
}
700
#endif
701

    
702
/* carry add/sub (we only need to set CC_OP differently) */
703

    
704
void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
705
{
706
    int cf;
707
    cf = cc_table[CC_OP].compute_c();
708
    CC_SRC = T0;
709
    T0 = T0 + T1 + cf;
710
    CC_DST = T0;
711
    CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
712
}
713

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

    
724
void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
725
{
726
    CC_SRC = EAX;
727
    CC_DST = EAX - T0;
728
    if ((DATA_TYPE)CC_DST == 0) {
729
        T0 = T1;
730
    } else {
731
        EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
732
    }
733
    FORCE_RET();
734
}
735

    
736
/* bit operations */
737
#if DATA_BITS >= 16
738

    
739
void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
740
{
741
    int count;
742
    count = T1 & SHIFT_MASK;
743
    CC_SRC = T0 >> count;
744
}
745

    
746
void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
747
{
748
    int count;
749
    count = T1 & SHIFT_MASK;
750
    CC_SRC = T0 >> count;
751
    T0 |= (1 << count);
752
}
753

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

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

    
770
void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
771
{
772
    int res, count;
773
    res = T0 & DATA_MASK;
774
    if (res != 0) {
775
        count = 0;
776
        while ((res & 1) == 0) {
777
            count++;
778
            res >>= 1;
779
        }
780
        T0 = count;
781
        CC_DST = 1; /* ZF = 1 */
782
    } else {
783
        CC_DST = 0; /* ZF = 1 */
784
    }
785
    FORCE_RET();
786
}
787

    
788
void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
789
{
790
    int res, count;
791
    res = T0 & DATA_MASK;
792
    if (res != 0) {
793
        count = DATA_BITS - 1;
794
        while ((res & SIGN_MASK) == 0) {
795
            count--;
796
            res <<= 1;
797
        }
798
        T0 = count;
799
        CC_DST = 1; /* ZF = 1 */
800
    } else {
801
        CC_DST = 0; /* ZF = 1 */
802
    }
803
    FORCE_RET();
804
}
805

    
806
#endif
807

    
808
/* string operations */
809
/* XXX: maybe use lower level instructions to ease exception handling */
810

    
811
void OPPROTO glue(op_movs, SUFFIX)(void)
812
{
813
    int v;
814
    v = glue(ldu, SUFFIX)((void *)ESI);
815
    glue(st, SUFFIX)((void *)EDI, v);
816
    ESI += (DF << SHIFT);
817
    EDI += (DF << SHIFT);
818
}
819

    
820
void OPPROTO glue(op_rep_movs, SUFFIX)(void)
821
{
822
    int v, inc;
823
    inc = (DF << SHIFT);
824
    while (ECX != 0) {
825
        v = glue(ldu, SUFFIX)((void *)ESI);
826
        glue(st, SUFFIX)((void *)EDI, v);
827
        ESI += inc;
828
        EDI += inc;
829
        ECX--;
830
    }
831
    FORCE_RET();
832
}
833

    
834
void OPPROTO glue(op_stos, SUFFIX)(void)
835
{
836
    glue(st, SUFFIX)((void *)EDI, EAX);
837
    EDI += (DF << SHIFT);
838
}
839

    
840
void OPPROTO glue(op_rep_stos, SUFFIX)(void)
841
{
842
    int inc;
843
    inc = (DF << SHIFT);
844
    while (ECX != 0) {
845
        glue(st, SUFFIX)((void *)EDI, EAX);
846
        EDI += inc;
847
        ECX--;
848
    }
849
    FORCE_RET();
850
}
851

    
852
void OPPROTO glue(op_lods, SUFFIX)(void)
853
{
854
    int v;
855
    v = glue(ldu, SUFFIX)((void *)ESI);
856
#if SHIFT == 0
857
    EAX = (EAX & ~0xff) | v;
858
#elif SHIFT == 1
859
    EAX = (EAX & ~0xffff) | v;
860
#else
861
    EAX = v;
862
#endif
863
    ESI += (DF << SHIFT);
864
}
865

    
866
/* don't know if it is used */
867
void OPPROTO glue(op_rep_lods, SUFFIX)(void)
868
{
869
    int v, inc;
870
    inc = (DF << SHIFT);
871
    while (ECX != 0) {
872
        v = glue(ldu, SUFFIX)((void *)ESI);
873
#if SHIFT == 0
874
        EAX = (EAX & ~0xff) | v;
875
#elif SHIFT == 1
876
        EAX = (EAX & ~0xffff) | v;
877
#else
878
        EAX = v;
879
#endif
880
        ESI += inc;
881
        ECX--;
882
    }
883
    FORCE_RET();
884
}
885

    
886
void OPPROTO glue(op_scas, SUFFIX)(void)
887
{
888
    int v;
889

    
890
    v = glue(ldu, SUFFIX)((void *)EDI);
891
    EDI += (DF << SHIFT);
892
    CC_SRC = EAX;
893
    CC_DST = EAX - v;
894
}
895

    
896
void OPPROTO glue(op_repz_scas, SUFFIX)(void)
897
{
898
    int v1, v2, inc;
899

    
900
    if (ECX != 0) {
901
        /* NOTE: the flags are not modified if ECX == 0 */
902
        v1 = EAX & DATA_MASK;
903
        inc = (DF << SHIFT);
904
        do {
905
            v2 = glue(ldu, SUFFIX)((void *)EDI);
906
            EDI += inc;
907
            ECX--;
908
            if (v1 != v2)
909
                break;
910
        } while (ECX != 0);
911
        CC_SRC = v1;
912
        CC_DST = v1 - v2;
913
        CC_OP = CC_OP_SUBB + SHIFT;
914
    }
915
    FORCE_RET();
916
}
917

    
918
void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
919
{
920
    int v1, v2, inc;
921

    
922
    if (ECX != 0) {
923
        /* NOTE: the flags are not modified if ECX == 0 */
924
        v1 = EAX & DATA_MASK;
925
        inc = (DF << SHIFT);
926
        do {
927
            v2 = glue(ldu, SUFFIX)((void *)EDI);
928
            EDI += inc;
929
            ECX--;
930
            if (v1 == v2)
931
                break;
932
        } while (ECX != 0);
933
        CC_SRC = v1;
934
        CC_DST = v1 - v2;
935
        CC_OP = CC_OP_SUBB + SHIFT;
936
    }
937
    FORCE_RET();
938
}
939

    
940
void OPPROTO glue(op_cmps, SUFFIX)(void)
941
{
942
    int v1, v2;
943
    v1 = glue(ldu, SUFFIX)((void *)ESI);
944
    v2 = glue(ldu, SUFFIX)((void *)EDI);
945
    ESI += (DF << SHIFT);
946
    EDI += (DF << SHIFT);
947
    CC_SRC = v1;
948
    CC_DST = v1 - v2;
949
}
950

    
951
void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
952
{
953
    int v1, v2, inc;
954
    if (ECX != 0) {
955
        inc = (DF << SHIFT);
956
        do {
957
            v1 = glue(ldu, SUFFIX)((void *)ESI);
958
            v2 = glue(ldu, SUFFIX)((void *)EDI);
959
            ESI += inc;
960
            EDI += inc;
961
            ECX--;
962
            if (v1 != v2)
963
                break;
964
        } while (ECX != 0);
965
        CC_SRC = v1;
966
        CC_DST = v1 - v2;
967
        CC_OP = CC_OP_SUBB + SHIFT;
968
    }
969
    FORCE_RET();
970
}
971

    
972
void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
973
{
974
    int v1, v2, inc;
975
    if (ECX != 0) {
976
        inc = (DF << SHIFT);
977
        do {
978
            v1 = glue(ldu, SUFFIX)((void *)ESI);
979
            v2 = glue(ldu, SUFFIX)((void *)EDI);
980
            ESI += inc;
981
            EDI += inc;
982
            ECX--;
983
            if (v1 == v2)
984
                break;
985
        } while (ECX != 0);
986
        CC_SRC = v1;
987
        CC_DST = v1 - v2;
988
        CC_OP = CC_OP_SUBB + SHIFT;
989
    }
990
    FORCE_RET();
991
}
992

    
993
/* port I/O */
994

    
995
void OPPROTO glue(op_outs, SUFFIX)(void)
996
{
997
    int v, dx;
998
    dx = EDX & 0xffff;
999
    v = glue(ldu, SUFFIX)((void *)ESI);
1000
    glue(cpu_x86_out, SUFFIX)(dx, v);
1001
    ESI += (DF << SHIFT);
1002
}
1003

    
1004
void OPPROTO glue(op_rep_outs, SUFFIX)(void)
1005
{
1006
    int v, dx, inc;
1007
    inc = (DF << SHIFT);
1008
    dx = EDX & 0xffff;
1009
    while (ECX != 0) {
1010
        v = glue(ldu, SUFFIX)((void *)ESI);
1011
        glue(cpu_x86_out, SUFFIX)(dx, v);
1012
        ESI += inc;
1013
        ECX--;
1014
    }
1015
    FORCE_RET();
1016
}
1017

    
1018
void OPPROTO glue(op_ins, SUFFIX)(void)
1019
{
1020
    int v, dx;
1021
    dx = EDX & 0xffff;
1022
    v = glue(cpu_x86_in, SUFFIX)(dx);
1023
    glue(st, SUFFIX)((void *)EDI, v);
1024
    EDI += (DF << SHIFT);
1025
}
1026

    
1027
void OPPROTO glue(op_rep_ins, SUFFIX)(void)
1028
{
1029
    int v, dx, inc;
1030
    inc = (DF << SHIFT);
1031
    dx = EDX & 0xffff;
1032
    while (ECX != 0) {
1033
        v = glue(cpu_x86_in, SUFFIX)(dx);
1034
        glue(st, SUFFIX)((void *)EDI, v);
1035
        EDI += (DF << SHIFT);
1036
        ECX--;
1037
    }
1038
    FORCE_RET();
1039
}
1040

    
1041
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
1042
{
1043
    glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
1044
}
1045

    
1046
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
1047
{
1048
    T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
1049
}
1050

    
1051
#undef DATA_BITS
1052
#undef SHIFT_MASK
1053
#undef SIGN_MASK
1054
#undef DATA_TYPE
1055
#undef DATA_STYPE
1056
#undef DATA_MASK
1057
#undef SUFFIX