Statistics
| Branch: | Revision:

root / ops_template.h @ b03c60f3

History | View | Annotate | Download (22.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 program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program 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
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
20
 */
21

    
22
#define DATA_BITS (1 << (3 + SHIFT))
23
#define SHIFT_MASK (DATA_BITS - 1)
24
#define SIGN_MASK (1 << (DATA_BITS - 1))
25

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

    
45
/* dynamic flags computation */
46

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
208
#if DATA_BITS == 32
209
static int glue(compute_c_shl, SUFFIX)(void)
210
{
211
    return CC_SRC & 1;
212
}
213
#endif
214

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

    
228
/* various optimized jumps cases */
229

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

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

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

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

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

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

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

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

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

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

    
300
/* oldies */
301

    
302
#if DATA_BITS >= 16
303

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

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

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

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

    
353
#endif
354

    
355
/* various optimized set cases */
356

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

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

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

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

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

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

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

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

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

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

    
403
/* shifts */
404

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
630

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

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

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

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

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

    
687

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

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

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

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

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

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

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

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

    
755
void OPPROTO glue(glue(op_btr, 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_btc, 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_bsf, SUFFIX), _T0_cc)(void)
772
{
773
    int res, count;
774
    res = T0 & DATA_MASK;
775
    if (res != 0) {
776
        count = 0;
777
        while ((res & 1) == 0) {
778
            count++;
779
            res >>= 1;
780
        }
781
        T0 = count;
782
        CC_DST = 1; /* ZF = 1 */
783
    } else {
784
        CC_DST = 0; /* ZF = 1 */
785
    }
786
    FORCE_RET();
787
}
788

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

    
807
#endif
808

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
994
/* port I/O */
995

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

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

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

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

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

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

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