]> git.proxmox.com Git - qemu.git/blame - ops_template.h
added flags computation optimization
[qemu.git] / ops_template.h
CommitLineData
367e86e8
FB
1
2#define DATA_BITS (1 << (3 + SHIFT))
3#define SHIFT_MASK (DATA_BITS - 1)
4#define SIGN_MASK (1 << (DATA_BITS - 1))
5
6#if DATA_BITS == 8
7#define SUFFIX b
8#define DATA_TYPE uint8_t
9#define DATA_STYPE int8_t
10#define DATA_MASK 0xff
11#elif DATA_BITS == 16
12#define SUFFIX w
13#define DATA_TYPE uint16_t
14#define DATA_STYPE int16_t
15#define DATA_MASK 0xffff
16#elif DATA_BITS == 32
17#define SUFFIX l
18#define DATA_TYPE uint32_t
19#define DATA_STYPE int32_t
20#define DATA_MASK 0xffffffff
21#else
22#error unhandled operand size
23#endif
24
25/* dynamic flags computation */
26
27static int glue(compute_all_add, SUFFIX)(void)
28{
29 int cf, pf, af, zf, sf, of;
30 int src1, src2;
31 src1 = CC_SRC;
32 src2 = CC_DST - CC_SRC;
33 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
34 pf = parity_table[(uint8_t)CC_DST];
35 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 36 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8
FB
37 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
38 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
39 return cf | pf | af | zf | sf | of;
40}
41
42static int glue(compute_c_add, SUFFIX)(void)
43{
44 int src1, cf;
45 src1 = CC_SRC;
46 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
47 return cf;
48}
49
4b74fe1f
FB
50static int glue(compute_all_adc, SUFFIX)(void)
51{
52 int cf, pf, af, zf, sf, of;
53 int src1, src2;
54 src1 = CC_SRC;
55 src2 = CC_DST - CC_SRC - 1;
56 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
57 pf = parity_table[(uint8_t)CC_DST];
58 af = (CC_DST ^ src1 ^ src2) & 0x10;
59 zf = ((DATA_TYPE)CC_DST == 0) << 6;
60 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
61 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
62 return cf | pf | af | zf | sf | of;
63}
64
65static int glue(compute_c_adc, SUFFIX)(void)
66{
67 int src1, cf;
68 src1 = CC_SRC;
69 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
70 return cf;
71}
72
367e86e8
FB
73static int glue(compute_all_sub, SUFFIX)(void)
74{
75 int cf, pf, af, zf, sf, of;
76 int src1, src2;
77 src1 = CC_SRC;
78 src2 = CC_SRC - CC_DST;
79 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
80 pf = parity_table[(uint8_t)CC_DST];
81 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 82 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 83 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
4b74fe1f 84 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
367e86e8
FB
85 return cf | pf | af | zf | sf | of;
86}
87
88static int glue(compute_c_sub, SUFFIX)(void)
89{
90 int src1, src2, cf;
91 src1 = CC_SRC;
92 src2 = CC_SRC - CC_DST;
4b74fe1f
FB
93 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
94 return cf;
95}
96
97static int glue(compute_all_sbb, SUFFIX)(void)
98{
99 int cf, pf, af, zf, sf, of;
100 int src1, src2;
101 src1 = CC_SRC;
102 src2 = CC_SRC - CC_DST - 1;
103 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
104 pf = parity_table[(uint8_t)CC_DST];
105 af = (CC_DST ^ src1 ^ src2) & 0x10;
106 zf = ((DATA_TYPE)CC_DST == 0) << 6;
107 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
108 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
109 return cf | pf | af | zf | sf | of;
110}
111
112static int glue(compute_c_sbb, SUFFIX)(void)
113{
114 int src1, src2, cf;
115 src1 = CC_SRC;
116 src2 = CC_SRC - CC_DST - 1;
117 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
367e86e8
FB
118 return cf;
119}
120
121static int glue(compute_all_logic, SUFFIX)(void)
122{
123 int cf, pf, af, zf, sf, of;
124 cf = 0;
125 pf = parity_table[(uint8_t)CC_DST];
126 af = 0;
4b74fe1f 127 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8
FB
128 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
129 of = 0;
130 return cf | pf | af | zf | sf | of;
131}
132
133static int glue(compute_c_logic, SUFFIX)(void)
134{
135 return 0;
136}
137
138static int glue(compute_all_inc, SUFFIX)(void)
139{
140 int cf, pf, af, zf, sf, of;
141 int src1, src2;
142 src1 = CC_DST - 1;
143 src2 = 1;
144 cf = CC_SRC;
145 pf = parity_table[(uint8_t)CC_DST];
146 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 147 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 148 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
4b74fe1f 149 of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
367e86e8
FB
150 return cf | pf | af | zf | sf | of;
151}
152
4b74fe1f 153#if DATA_BITS == 32
367e86e8
FB
154static int glue(compute_c_inc, SUFFIX)(void)
155{
156 return CC_SRC;
157}
4b74fe1f 158#endif
367e86e8
FB
159
160static int glue(compute_all_dec, SUFFIX)(void)
161{
162 int cf, pf, af, zf, sf, of;
163 int src1, src2;
164 src1 = CC_DST + 1;
165 src2 = 1;
166 cf = CC_SRC;
167 pf = parity_table[(uint8_t)CC_DST];
168 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 169 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 170 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
4b74fe1f 171 of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11;
367e86e8
FB
172 return cf | pf | af | zf | sf | of;
173}
174
175static int glue(compute_all_shl, SUFFIX)(void)
176{
177 int cf, pf, af, zf, sf, of;
d57c4e01 178 cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
367e86e8
FB
179 pf = parity_table[(uint8_t)CC_DST];
180 af = 0; /* undefined */
4b74fe1f 181 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 182 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
d57c4e01
FB
183 /* of is defined if shift count == 1 */
184 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
367e86e8
FB
185 return cf | pf | af | zf | sf | of;
186}
187
4b74fe1f 188#if DATA_BITS == 32
367e86e8
FB
189static int glue(compute_c_shl, SUFFIX)(void)
190{
191 return CC_SRC & 1;
192}
4b74fe1f
FB
193#endif
194
195static int glue(compute_all_sar, SUFFIX)(void)
196{
197 int cf, pf, af, zf, sf, of;
198 cf = CC_SRC & 1;
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;
d57c4e01
FB
203 /* of is defined if shift count == 1 */
204 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
4b74fe1f
FB
205 return cf | pf | af | zf | sf | of;
206}
367e86e8
FB
207
208/* various optimized jumps cases */
209
210void OPPROTO glue(op_jb_sub, SUFFIX)(void)
211{
212 int src1, src2;
213 src1 = CC_SRC;
214 src2 = CC_SRC - CC_DST;
215
216 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
0ecfa993 217 PC = PARAM1;
367e86e8 218 else
0ecfa993 219 PC = PARAM2;
367e86e8
FB
220 FORCE_RET();
221}
222
223void OPPROTO glue(op_jz_sub, SUFFIX)(void)
224{
4b74fe1f 225 if ((DATA_TYPE)CC_DST == 0)
0ecfa993 226 PC = PARAM1;
367e86e8 227 else
0ecfa993 228 PC = PARAM2;
367e86e8
FB
229 FORCE_RET();
230}
231
232void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
233{
234 int src1, src2;
235 src1 = CC_SRC;
236 src2 = CC_SRC - CC_DST;
237
238 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
0ecfa993 239 PC = PARAM1;
367e86e8 240 else
0ecfa993 241 PC = PARAM2;
367e86e8
FB
242 FORCE_RET();
243}
244
245void OPPROTO glue(op_js_sub, SUFFIX)(void)
246{
247 if (CC_DST & SIGN_MASK)
0ecfa993 248 PC = PARAM1;
367e86e8 249 else
0ecfa993 250 PC = PARAM2;
367e86e8
FB
251 FORCE_RET();
252}
253
254void OPPROTO glue(op_jl_sub, SUFFIX)(void)
255{
256 int src1, src2;
257 src1 = CC_SRC;
258 src2 = CC_SRC - CC_DST;
259
260 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
0ecfa993 261 PC = PARAM1;
367e86e8 262 else
0ecfa993 263 PC = PARAM2;
367e86e8
FB
264 FORCE_RET();
265}
266
267void OPPROTO glue(op_jle_sub, SUFFIX)(void)
268{
269 int src1, src2;
270 src1 = CC_SRC;
271 src2 = CC_SRC - CC_DST;
272
273 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
0ecfa993 274 PC = PARAM1;
367e86e8 275 else
0ecfa993 276 PC = PARAM2;
367e86e8
FB
277 FORCE_RET();
278}
279
1a9353d2
FB
280/* oldies */
281
282#if DATA_BITS >= 16
283
284void OPPROTO glue(op_loopnz, SUFFIX)(void)
285{
286 unsigned int tmp;
287 int eflags;
288 eflags = cc_table[CC_OP].compute_all();
289 tmp = (ECX - 1) & DATA_MASK;
290 ECX = (ECX & ~DATA_MASK) | tmp;
291 if (tmp != 0 && !(eflags & CC_Z))
292 PC = PARAM1;
293 else
294 PC = PARAM2;
295 FORCE_RET();
296}
297
298void OPPROTO glue(op_loopz, SUFFIX)(void)
299{
300 unsigned int tmp;
301 int eflags;
302 eflags = cc_table[CC_OP].compute_all();
303 tmp = (ECX - 1) & DATA_MASK;
304 ECX = (ECX & ~DATA_MASK) | tmp;
305 if (tmp != 0 && (eflags & CC_Z))
306 PC = PARAM1;
307 else
308 PC = PARAM2;
309 FORCE_RET();
310}
311
312void OPPROTO glue(op_loop, SUFFIX)(void)
313{
314 unsigned int tmp;
315 tmp = (ECX - 1) & DATA_MASK;
316 ECX = (ECX & ~DATA_MASK) | tmp;
317 if (tmp != 0)
318 PC = PARAM1;
319 else
320 PC = PARAM2;
321 FORCE_RET();
322}
323
324void OPPROTO glue(op_jecxz, SUFFIX)(void)
325{
326 if ((DATA_TYPE)ECX == 0)
327 PC = PARAM1;
328 else
329 PC = PARAM2;
330 FORCE_RET();
331}
332
333#endif
334
367e86e8
FB
335/* various optimized set cases */
336
337void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
338{
339 int src1, src2;
340 src1 = CC_SRC;
341 src2 = CC_SRC - CC_DST;
342
343 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
344}
345
346void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
347{
4b74fe1f 348 T0 = ((DATA_TYPE)CC_DST == 0);
367e86e8
FB
349}
350
351void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
352{
353 int src1, src2;
354 src1 = CC_SRC;
355 src2 = CC_SRC - CC_DST;
356
357 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
358}
359
360void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
361{
362 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
363}
364
365void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
366{
367 int src1, src2;
368 src1 = CC_SRC;
369 src2 = CC_SRC - CC_DST;
370
371 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
372}
373
374void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
375{
376 int src1, src2;
377 src1 = CC_SRC;
378 src2 = CC_SRC - CC_DST;
379
380 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
381}
382
383/* shifts */
384
385void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
386{
387 int count, src;
388 count = T1 & SHIFT_MASK;
389 if (count) {
390 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
391 src = T0;
392 T0 &= DATA_MASK;
393 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
394 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
395 (T0 & CC_C);
396 CC_OP = CC_OP_EFLAGS;
397 }
4b74fe1f 398 FORCE_RET();
367e86e8
FB
399}
400
dc99065b
FB
401void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void)
402{
403 int count;
404 count = T1 & SHIFT_MASK;
405 if (count) {
406 T0 &= DATA_MASK;
407 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
408 }
409 FORCE_RET();
410}
411
367e86e8
FB
412void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
413{
414 int count, src;
415 count = T1 & SHIFT_MASK;
416 if (count) {
417 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
418 src = T0;
419 T0 &= DATA_MASK;
420 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
421 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
422 ((T0 >> (DATA_BITS - 1)) & CC_C);
423 CC_OP = CC_OP_EFLAGS;
424 }
4b74fe1f 425 FORCE_RET();
367e86e8
FB
426}
427
dc99065b
FB
428void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void)
429{
430 int count;
431 count = T1 & SHIFT_MASK;
432 if (count) {
433 T0 &= DATA_MASK;
434 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
435 }
436 FORCE_RET();
437}
438
367e86e8
FB
439void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
440{
441 int count, res, eflags;
442 unsigned int src;
443
444 count = T1 & 0x1f;
445#if DATA_BITS == 16
446 count = rclw_table[count];
447#elif DATA_BITS == 8
448 count = rclb_table[count];
449#endif
450 if (count) {
451 eflags = cc_table[CC_OP].compute_all();
4b74fe1f 452 T0 &= DATA_MASK;
367e86e8
FB
453 src = T0;
454 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
455 if (count > 1)
456 res |= T0 >> (DATA_BITS + 1 - count);
457 T0 = res;
458 CC_SRC = (eflags & ~(CC_C | CC_O)) |
459 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
460 ((src >> (DATA_BITS - count)) & CC_C);
461 CC_OP = CC_OP_EFLAGS;
462 }
4b74fe1f 463 FORCE_RET();
367e86e8
FB
464}
465
466void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
467{
468 int count, res, eflags;
469 unsigned int src;
470
471 count = T1 & 0x1f;
472#if DATA_BITS == 16
473 count = rclw_table[count];
474#elif DATA_BITS == 8
475 count = rclb_table[count];
476#endif
477 if (count) {
478 eflags = cc_table[CC_OP].compute_all();
4b74fe1f 479 T0 &= DATA_MASK;
367e86e8
FB
480 src = T0;
481 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
482 if (count > 1)
483 res |= T0 << (DATA_BITS + 1 - count);
484 T0 = res;
485 CC_SRC = (eflags & ~(CC_C | CC_O)) |
486 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
487 ((src >> (count - 1)) & CC_C);
488 CC_OP = CC_OP_EFLAGS;
489 }
4b74fe1f 490 FORCE_RET();
367e86e8
FB
491}
492
493void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
494{
495 int count;
496 count = T1 & 0x1f;
d57c4e01
FB
497 if (count) {
498 CC_SRC = (DATA_TYPE)T0 << (count - 1);
367e86e8
FB
499 T0 = T0 << count;
500 CC_DST = T0;
501 CC_OP = CC_OP_SHLB + SHIFT;
502 }
4b74fe1f 503 FORCE_RET();
367e86e8
FB
504}
505
dc99065b
FB
506void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
507{
508 int count;
509 count = T1 & 0x1f;
510 T0 = T0 << count;
511 FORCE_RET();
512}
513
367e86e8
FB
514void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
515{
516 int count;
517 count = T1 & 0x1f;
518 if (count) {
519 T0 &= DATA_MASK;
520 CC_SRC = T0 >> (count - 1);
521 T0 = T0 >> count;
522 CC_DST = T0;
d57c4e01 523 CC_OP = CC_OP_SARB + SHIFT;
367e86e8 524 }
4b74fe1f 525 FORCE_RET();
367e86e8
FB
526}
527
dc99065b
FB
528void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
529{
530 int count;
531 count = T1 & 0x1f;
532 T0 &= DATA_MASK;
533 T0 = T0 >> count;
534 FORCE_RET();
535}
536
367e86e8
FB
537void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
538{
539 int count, src;
540 count = T1 & 0x1f;
541 if (count) {
542 src = (DATA_STYPE)T0;
d57c4e01 543 CC_SRC = src >> (count - 1);
367e86e8
FB
544 T0 = src >> count;
545 CC_DST = T0;
4b74fe1f 546 CC_OP = CC_OP_SARB + SHIFT;
367e86e8 547 }
4b74fe1f 548 FORCE_RET();
367e86e8
FB
549}
550
dc99065b
FB
551void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
552{
553 int count, src;
554 count = T1 & 0x1f;
555 src = (DATA_STYPE)T0;
556 T0 = src >> count;
557 FORCE_RET();
558}
559
d57c4e01
FB
560#if DATA_BITS == 16
561/* XXX: overflow flag might be incorrect in some cases in shldw */
562void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
563{
564 int count;
565 unsigned int res;
566 count = PARAM1;
567 T1 &= 0xffff;
568 res = T1 | (T0 << 16);
569 CC_SRC = res >> (32 - count);
570 res <<= count;
571 if (count > 16)
572 res |= T1 << (count - 16);
573 T0 = res >> 16;
574 CC_DST = T0;
575}
576
577void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
578{
579 int count;
580 unsigned int res;
581 count = ECX & 0x1f;
582 if (count) {
583 T1 &= 0xffff;
584 res = T1 | (T0 << 16);
585 CC_SRC = res >> (32 - count);
586 res <<= count;
587 if (count > 16)
588 res |= T1 << (count - 16);
589 T0 = res >> 16;
590 CC_DST = T0;
591 CC_OP = CC_OP_SARB + SHIFT;
592 }
593}
594
595void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
596{
597 int count;
598 unsigned int res;
599
600 count = PARAM1;
601 res = (T0 & 0xffff) | (T1 << 16);
602 CC_SRC = res >> (count - 1);
603 res >>= count;
604 if (count > 16)
605 res |= T1 << (32 - count);
606 T0 = res;
607 CC_DST = T0;
608}
609
610
611void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
612{
613 int count;
614 unsigned int res;
615
616 count = ECX & 0x1f;
617 if (count) {
618 res = (T0 & 0xffff) | (T1 << 16);
619 CC_SRC = res >> (count - 1);
620 res >>= count;
621 if (count > 16)
622 res |= T1 << (32 - count);
623 T0 = res;
624 CC_DST = T0;
625 CC_OP = CC_OP_SARB + SHIFT;
626 }
627}
628#endif
629
630#if DATA_BITS == 32
631void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
632{
633 int count;
634 count = PARAM1;
635 T0 &= DATA_MASK;
636 T1 &= DATA_MASK;
637 CC_SRC = T0 << (count - 1);
638 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
639 CC_DST = T0;
640}
641
642void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
643{
644 int count;
645 count = ECX & 0x1f;
646 if (count) {
647 T0 &= DATA_MASK;
648 T1 &= DATA_MASK;
649 CC_SRC = T0 << (count - 1);
650 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
651 CC_DST = T0;
652 CC_OP = CC_OP_SHLB + SHIFT;
653 }
654}
655
656void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
657{
658 int count;
659 count = PARAM1;
660 T0 &= DATA_MASK;
661 T1 &= DATA_MASK;
662 CC_SRC = T0 >> (count - 1);
663 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
664 CC_DST = T0;
665}
666
667
668void OPPROTO glue(glue(op_shrd, 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_SARB + SHIFT;
679 }
680}
681#endif
682
4b74fe1f
FB
683/* carry add/sub (we only need to set CC_OP differently) */
684
685void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
686{
687 int cf;
688 cf = cc_table[CC_OP].compute_c();
689 CC_SRC = T0;
690 T0 = T0 + T1 + cf;
691 CC_DST = T0;
692 CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
693}
694
695void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
696{
697 int cf;
698 cf = cc_table[CC_OP].compute_c();
699 CC_SRC = T0;
700 T0 = T0 - T1 - cf;
701 CC_DST = T0;
702 CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
703}
704
1a9353d2
FB
705void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
706{
707 CC_SRC = EAX;
708 CC_DST = EAX - T0;
709 if ((DATA_TYPE)CC_DST == 0) {
710 T0 = T1;
711 } else {
712 EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
713 }
714 FORCE_RET();
715}
716
4b74fe1f
FB
717/* bit operations */
718#if DATA_BITS >= 16
719
720void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
721{
722 int count;
723 count = T1 & SHIFT_MASK;
724 CC_SRC = T0 >> count;
725}
726
727void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
728{
729 int count;
730 count = T1 & SHIFT_MASK;
731 CC_SRC = T0 >> count;
732 T0 |= (1 << count);
733}
734
735void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
736{
737 int count;
738 count = T1 & SHIFT_MASK;
739 CC_SRC = T0 >> count;
740 T0 &= ~(1 << count);
741}
742
743void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
744{
745 int count;
746 count = T1 & SHIFT_MASK;
747 CC_SRC = T0 >> count;
748 T0 ^= (1 << count);
749}
750
77f8dd5a
FB
751void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
752{
753 int res, count;
754 res = T0 & DATA_MASK;
755 if (res != 0) {
756 count = 0;
757 while ((res & 1) == 0) {
758 count++;
759 res >>= 1;
760 }
761 T0 = count;
762 CC_DST = 1; /* ZF = 1 */
763 } else {
764 CC_DST = 0; /* ZF = 1 */
765 }
766 FORCE_RET();
767}
768
769void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
770{
771 int res, count;
772 res = T0 & DATA_MASK;
773 if (res != 0) {
774 count = DATA_BITS - 1;
775 while ((res & SIGN_MASK) == 0) {
776 count--;
777 res <<= 1;
778 }
779 T0 = count;
780 CC_DST = 1; /* ZF = 1 */
781 } else {
782 CC_DST = 0; /* ZF = 1 */
783 }
784 FORCE_RET();
785}
786
4b74fe1f
FB
787#endif
788
367e86e8
FB
789/* string operations */
790/* XXX: maybe use lower level instructions to ease exception handling */
791
792void OPPROTO glue(op_movs, SUFFIX)(void)
793{
794 int v;
795 v = glue(ldu, SUFFIX)((void *)ESI);
796 glue(st, SUFFIX)((void *)EDI, v);
797 ESI += (DF << SHIFT);
798 EDI += (DF << SHIFT);
799}
800
801void OPPROTO glue(op_rep_movs, SUFFIX)(void)
802{
803 int v, inc;
804 inc = (DF << SHIFT);
805 while (ECX != 0) {
806 v = glue(ldu, SUFFIX)((void *)ESI);
807 glue(st, SUFFIX)((void *)EDI, v);
808 ESI += inc;
809 EDI += inc;
810 ECX--;
811 }
812}
813
814void OPPROTO glue(op_stos, SUFFIX)(void)
815{
816 glue(st, SUFFIX)((void *)EDI, EAX);
817 EDI += (DF << SHIFT);
818}
819
820void OPPROTO glue(op_rep_stos, SUFFIX)(void)
821{
822 int inc;
823 inc = (DF << SHIFT);
824 while (ECX != 0) {
825 glue(st, SUFFIX)((void *)EDI, EAX);
826 EDI += inc;
827 ECX--;
828 }
829}
830
831void OPPROTO glue(op_lods, SUFFIX)(void)
832{
833 int v;
834 v = glue(ldu, SUFFIX)((void *)ESI);
835#if SHIFT == 0
836 EAX = (EAX & ~0xff) | v;
837#elif SHIFT == 1
838 EAX = (EAX & ~0xffff) | v;
839#else
840 EAX = v;
841#endif
842 ESI += (DF << SHIFT);
843}
844
845/* don't know if it is used */
846void OPPROTO glue(op_rep_lods, SUFFIX)(void)
847{
848 int v, inc;
849 inc = (DF << SHIFT);
850 while (ECX != 0) {
851 v = glue(ldu, SUFFIX)((void *)ESI);
852#if SHIFT == 0
853 EAX = (EAX & ~0xff) | v;
854#elif SHIFT == 1
855 EAX = (EAX & ~0xffff) | v;
856#else
857 EAX = v;
858#endif
859 ESI += inc;
860 ECX--;
861 }
862}
863
864void OPPROTO glue(op_scas, SUFFIX)(void)
865{
866 int v;
867
4b74fe1f
FB
868 v = glue(ldu, SUFFIX)((void *)EDI);
869 EDI += (DF << SHIFT);
367e86e8
FB
870 CC_SRC = EAX;
871 CC_DST = EAX - v;
872}
873
874void OPPROTO glue(op_repz_scas, SUFFIX)(void)
875{
876 int v1, v2, inc;
877
878 if (ECX != 0) {
879 /* NOTE: the flags are not modified if ECX == 0 */
4b74fe1f 880 v1 = EAX & DATA_MASK;
367e86e8
FB
881 inc = (DF << SHIFT);
882 do {
4b74fe1f
FB
883 v2 = glue(ldu, SUFFIX)((void *)EDI);
884 EDI += inc;
885 ECX--;
367e86e8
FB
886 if (v1 != v2)
887 break;
367e86e8
FB
888 } while (ECX != 0);
889 CC_SRC = v1;
890 CC_DST = v1 - v2;
891 CC_OP = CC_OP_SUBB + SHIFT;
892 }
893}
894
895void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
896{
897 int v1, v2, inc;
898
899 if (ECX != 0) {
900 /* NOTE: the flags are not modified if ECX == 0 */
4b74fe1f 901 v1 = EAX & DATA_MASK;
367e86e8
FB
902 inc = (DF << SHIFT);
903 do {
4b74fe1f
FB
904 v2 = glue(ldu, SUFFIX)((void *)EDI);
905 EDI += inc;
906 ECX--;
367e86e8
FB
907 if (v1 == v2)
908 break;
367e86e8
FB
909 } while (ECX != 0);
910 CC_SRC = v1;
911 CC_DST = v1 - v2;
912 CC_OP = CC_OP_SUBB + SHIFT;
913 }
914}
915
916void OPPROTO glue(op_cmps, SUFFIX)(void)
917{
918 int v1, v2;
919 v1 = glue(ldu, SUFFIX)((void *)ESI);
920 v2 = glue(ldu, SUFFIX)((void *)EDI);
921 ESI += (DF << SHIFT);
922 EDI += (DF << SHIFT);
923 CC_SRC = v1;
924 CC_DST = v1 - v2;
925}
926
927void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
928{
929 int v1, v2, inc;
930 if (ECX != 0) {
931 inc = (DF << SHIFT);
932 do {
933 v1 = glue(ldu, SUFFIX)((void *)ESI);
934 v2 = glue(ldu, SUFFIX)((void *)EDI);
367e86e8
FB
935 ESI += inc;
936 EDI += inc;
937 ECX--;
4b74fe1f
FB
938 if (v1 != v2)
939 break;
367e86e8
FB
940 } while (ECX != 0);
941 CC_SRC = v1;
942 CC_DST = v1 - v2;
943 CC_OP = CC_OP_SUBB + SHIFT;
944 }
945}
946
947void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
948{
949 int v1, v2, inc;
950 if (ECX != 0) {
951 inc = (DF << SHIFT);
952 do {
953 v1 = glue(ldu, SUFFIX)((void *)ESI);
954 v2 = glue(ldu, SUFFIX)((void *)EDI);
367e86e8
FB
955 ESI += inc;
956 EDI += inc;
957 ECX--;
4b74fe1f
FB
958 if (v1 == v2)
959 break;
367e86e8
FB
960 } while (ECX != 0);
961 CC_SRC = v1;
962 CC_DST = v1 - v2;
963 CC_OP = CC_OP_SUBB + SHIFT;
964 }
965}
966
ba1c6e37
FB
967/* port I/O */
968
367e86e8
FB
969void OPPROTO glue(op_outs, SUFFIX)(void)
970{
971 int v, dx;
972 dx = EDX & 0xffff;
973 v = glue(ldu, SUFFIX)((void *)ESI);
ba1c6e37 974 glue(cpu_x86_out, SUFFIX)(dx, v);
367e86e8
FB
975 ESI += (DF << SHIFT);
976}
977
978void OPPROTO glue(op_rep_outs, SUFFIX)(void)
979{
980 int v, dx, inc;
981 inc = (DF << SHIFT);
982 dx = EDX & 0xffff;
983 while (ECX != 0) {
984 v = glue(ldu, SUFFIX)((void *)ESI);
ba1c6e37 985 glue(cpu_x86_out, SUFFIX)(dx, v);
367e86e8
FB
986 ESI += inc;
987 ECX--;
988 }
989}
990
991void OPPROTO glue(op_ins, SUFFIX)(void)
992{
993 int v, dx;
994 dx = EDX & 0xffff;
ba1c6e37 995 v = glue(cpu_x86_in, SUFFIX)(dx);
367e86e8
FB
996 glue(st, SUFFIX)((void *)EDI, v);
997 EDI += (DF << SHIFT);
998}
999
1000void OPPROTO glue(op_rep_ins, SUFFIX)(void)
1001{
1002 int v, dx, inc;
1003 inc = (DF << SHIFT);
1004 dx = EDX & 0xffff;
1005 while (ECX != 0) {
ba1c6e37 1006 v = glue(cpu_x86_in, SUFFIX)(dx);
367e86e8
FB
1007 glue(st, SUFFIX)((void *)EDI, v);
1008 EDI += (DF << SHIFT);
1009 ECX--;
1010 }
1011}
1012
ba1c6e37
FB
1013void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
1014{
1015 glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
1016}
1017
1018void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
1019{
1020 T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
1021}
1022
367e86e8
FB
1023#undef DATA_BITS
1024#undef SHIFT_MASK
1025#undef SIGN_MASK
1026#undef DATA_TYPE
1027#undef DATA_STYPE
1028#undef DATA_MASK
1029#undef SUFFIX