Statistics
| Branch: | Revision:

root / ops_template.h @ a412ac57

History | View | Annotate | Download (12.7 kB)

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

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

    
44
/* dynamic flags computation */
45

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
232
/* various optimized jumps cases */
233

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

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

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

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

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

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

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

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

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

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

    
304
/* oldies */
305

    
306
#if DATA_BITS >= 16
307

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

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

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

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

    
357
#endif
358

    
359
/* various optimized set cases */
360

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

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

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

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

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

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

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

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

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

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

    
407
/* shifts */
408

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

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

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

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

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

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

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

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

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

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

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

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

    
511
#endif
512

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

    
520
/* string operations */
521
/* XXX: maybe use lower level instructions to ease 16 bit / segment handling */
522

    
523
#define STRING_SUFFIX _fast
524
#define SI_ADDR (void *)ESI
525
#define DI_ADDR (void *)EDI
526
#define INC_SI() ESI += inc
527
#define INC_DI() EDI += inc
528
#define CX ECX
529
#define DEC_CX() ECX--
530
#include "op_string.h"
531

    
532
#define STRING_SUFFIX _a32
533
#define SI_ADDR (uint8_t *)A0 + ESI
534
#define DI_ADDR env->segs[R_ES].base + EDI
535
#define INC_SI() ESI += inc
536
#define INC_DI() EDI += inc
537
#define CX ECX
538
#define DEC_CX() ECX--
539
#include "op_string.h"
540

    
541
#define STRING_SUFFIX _a16
542
#define SI_ADDR (uint8_t *)A0 + (ESI & 0xffff)
543
#define DI_ADDR env->segs[R_ES].base + (EDI & 0xffff)
544
#define INC_SI() ESI = (ESI & ~0xffff) | ((ESI + inc) & 0xffff)
545
#define INC_DI() EDI = (EDI & ~0xffff) | ((EDI + inc) & 0xffff)
546
#define CX (ECX & 0xffff)
547
#define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
548
#include "op_string.h"
549

    
550
/* port I/O */
551

    
552
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
553
{
554
    glue(cpu_x86_out, SUFFIX)(env, T0 & 0xffff, T1 & DATA_MASK);
555
}
556

    
557
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
558
{
559
    T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff);
560
}
561

    
562
#undef DATA_BITS
563
#undef SHIFT_MASK
564
#undef SIGN_MASK
565
#undef DATA_TYPE
566
#undef DATA_STYPE
567
#undef DATA_MASK
568
#undef SUFFIX