]> git.ipfire.org Git - thirdparty/qemu.git/blame - ops_template.h
better 16 bit code support
[thirdparty/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)
dab2ed99 217 EIP = PARAM1;
367e86e8 218 else
dab2ed99 219 EIP = 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)
dab2ed99 226 EIP = PARAM1;
367e86e8 227 else
dab2ed99 228 EIP = 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)
dab2ed99 239 EIP = PARAM1;
367e86e8 240 else
dab2ed99 241 EIP = PARAM2;
367e86e8
FB
242 FORCE_RET();
243}
244
245void OPPROTO glue(op_js_sub, SUFFIX)(void)
246{
247 if (CC_DST & SIGN_MASK)
dab2ed99 248 EIP = PARAM1;
367e86e8 249 else
dab2ed99 250 EIP = 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)
dab2ed99 261 EIP = PARAM1;
367e86e8 262 else
dab2ed99 263 EIP = 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)
dab2ed99 274 EIP = PARAM1;
367e86e8 275 else
dab2ed99 276 EIP = 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))
dab2ed99 292 EIP = PARAM1;
1a9353d2 293 else
dab2ed99 294 EIP = PARAM2;
1a9353d2
FB
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))
dab2ed99 306 EIP = PARAM1;
1a9353d2 307 else
dab2ed99 308 EIP = PARAM2;
1a9353d2
FB
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)
dab2ed99 318 EIP = PARAM1;
1a9353d2 319 else
dab2ed99 320 EIP = PARAM2;
1a9353d2
FB
321 FORCE_RET();
322}
323
324void OPPROTO glue(op_jecxz, SUFFIX)(void)
325{
326 if ((DATA_TYPE)ECX == 0)
dab2ed99 327 EIP = PARAM1;
1a9353d2 328 else
dab2ed99 329 EIP = PARAM2;
1a9353d2
FB
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 }
04369ff2 812 FORCE_RET();
367e86e8
FB
813}
814
815void OPPROTO glue(op_stos, SUFFIX)(void)
816{
817 glue(st, SUFFIX)((void *)EDI, EAX);
818 EDI += (DF << SHIFT);
819}
820
821void OPPROTO glue(op_rep_stos, SUFFIX)(void)
822{
823 int inc;
824 inc = (DF << SHIFT);
825 while (ECX != 0) {
826 glue(st, SUFFIX)((void *)EDI, EAX);
827 EDI += inc;
828 ECX--;
829 }
04369ff2 830 FORCE_RET();
367e86e8
FB
831}
832
833void OPPROTO glue(op_lods, SUFFIX)(void)
834{
835 int v;
836 v = glue(ldu, SUFFIX)((void *)ESI);
837#if SHIFT == 0
838 EAX = (EAX & ~0xff) | v;
839#elif SHIFT == 1
840 EAX = (EAX & ~0xffff) | v;
841#else
842 EAX = v;
843#endif
844 ESI += (DF << SHIFT);
845}
846
847/* don't know if it is used */
848void OPPROTO glue(op_rep_lods, SUFFIX)(void)
849{
850 int v, inc;
851 inc = (DF << SHIFT);
852 while (ECX != 0) {
853 v = glue(ldu, SUFFIX)((void *)ESI);
854#if SHIFT == 0
855 EAX = (EAX & ~0xff) | v;
856#elif SHIFT == 1
857 EAX = (EAX & ~0xffff) | v;
858#else
859 EAX = v;
860#endif
861 ESI += inc;
862 ECX--;
863 }
04369ff2 864 FORCE_RET();
367e86e8
FB
865}
866
867void OPPROTO glue(op_scas, SUFFIX)(void)
868{
869 int v;
870
4b74fe1f
FB
871 v = glue(ldu, SUFFIX)((void *)EDI);
872 EDI += (DF << SHIFT);
367e86e8
FB
873 CC_SRC = EAX;
874 CC_DST = EAX - v;
875}
876
877void OPPROTO glue(op_repz_scas, SUFFIX)(void)
878{
879 int v1, v2, inc;
880
881 if (ECX != 0) {
882 /* NOTE: the flags are not modified if ECX == 0 */
4b74fe1f 883 v1 = EAX & DATA_MASK;
367e86e8
FB
884 inc = (DF << SHIFT);
885 do {
4b74fe1f
FB
886 v2 = glue(ldu, SUFFIX)((void *)EDI);
887 EDI += inc;
888 ECX--;
367e86e8
FB
889 if (v1 != v2)
890 break;
367e86e8
FB
891 } while (ECX != 0);
892 CC_SRC = v1;
893 CC_DST = v1 - v2;
894 CC_OP = CC_OP_SUBB + SHIFT;
895 }
04369ff2 896 FORCE_RET();
367e86e8
FB
897}
898
899void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
900{
901 int v1, v2, inc;
902
903 if (ECX != 0) {
904 /* NOTE: the flags are not modified if ECX == 0 */
4b74fe1f 905 v1 = EAX & DATA_MASK;
367e86e8
FB
906 inc = (DF << SHIFT);
907 do {
4b74fe1f
FB
908 v2 = glue(ldu, SUFFIX)((void *)EDI);
909 EDI += inc;
910 ECX--;
367e86e8
FB
911 if (v1 == v2)
912 break;
367e86e8
FB
913 } while (ECX != 0);
914 CC_SRC = v1;
915 CC_DST = v1 - v2;
916 CC_OP = CC_OP_SUBB + SHIFT;
917 }
04369ff2 918 FORCE_RET();
367e86e8
FB
919}
920
921void OPPROTO glue(op_cmps, SUFFIX)(void)
922{
923 int v1, v2;
924 v1 = glue(ldu, SUFFIX)((void *)ESI);
925 v2 = glue(ldu, SUFFIX)((void *)EDI);
926 ESI += (DF << SHIFT);
927 EDI += (DF << SHIFT);
928 CC_SRC = v1;
929 CC_DST = v1 - v2;
930}
931
932void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
933{
934 int v1, v2, inc;
935 if (ECX != 0) {
936 inc = (DF << SHIFT);
937 do {
938 v1 = glue(ldu, SUFFIX)((void *)ESI);
939 v2 = glue(ldu, SUFFIX)((void *)EDI);
367e86e8
FB
940 ESI += inc;
941 EDI += inc;
942 ECX--;
4b74fe1f
FB
943 if (v1 != v2)
944 break;
367e86e8
FB
945 } while (ECX != 0);
946 CC_SRC = v1;
947 CC_DST = v1 - v2;
948 CC_OP = CC_OP_SUBB + SHIFT;
949 }
04369ff2 950 FORCE_RET();
367e86e8
FB
951}
952
953void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
954{
955 int v1, v2, inc;
956 if (ECX != 0) {
957 inc = (DF << SHIFT);
958 do {
959 v1 = glue(ldu, SUFFIX)((void *)ESI);
960 v2 = glue(ldu, SUFFIX)((void *)EDI);
367e86e8
FB
961 ESI += inc;
962 EDI += inc;
963 ECX--;
4b74fe1f
FB
964 if (v1 == v2)
965 break;
367e86e8
FB
966 } while (ECX != 0);
967 CC_SRC = v1;
968 CC_DST = v1 - v2;
969 CC_OP = CC_OP_SUBB + SHIFT;
970 }
04369ff2 971 FORCE_RET();
367e86e8
FB
972}
973
ba1c6e37
FB
974/* port I/O */
975
367e86e8
FB
976void OPPROTO glue(op_outs, SUFFIX)(void)
977{
978 int v, dx;
979 dx = EDX & 0xffff;
980 v = glue(ldu, SUFFIX)((void *)ESI);
ba1c6e37 981 glue(cpu_x86_out, SUFFIX)(dx, v);
367e86e8
FB
982 ESI += (DF << SHIFT);
983}
984
985void OPPROTO glue(op_rep_outs, SUFFIX)(void)
986{
987 int v, dx, inc;
988 inc = (DF << SHIFT);
989 dx = EDX & 0xffff;
990 while (ECX != 0) {
991 v = glue(ldu, SUFFIX)((void *)ESI);
ba1c6e37 992 glue(cpu_x86_out, SUFFIX)(dx, v);
367e86e8
FB
993 ESI += inc;
994 ECX--;
995 }
04369ff2 996 FORCE_RET();
367e86e8
FB
997}
998
999void OPPROTO glue(op_ins, SUFFIX)(void)
1000{
1001 int v, dx;
1002 dx = EDX & 0xffff;
ba1c6e37 1003 v = glue(cpu_x86_in, SUFFIX)(dx);
367e86e8
FB
1004 glue(st, SUFFIX)((void *)EDI, v);
1005 EDI += (DF << SHIFT);
1006}
1007
1008void OPPROTO glue(op_rep_ins, SUFFIX)(void)
1009{
1010 int v, dx, inc;
1011 inc = (DF << SHIFT);
1012 dx = EDX & 0xffff;
1013 while (ECX != 0) {
ba1c6e37 1014 v = glue(cpu_x86_in, SUFFIX)(dx);
367e86e8
FB
1015 glue(st, SUFFIX)((void *)EDI, v);
1016 EDI += (DF << SHIFT);
1017 ECX--;
1018 }
04369ff2 1019 FORCE_RET();
367e86e8
FB
1020}
1021
ba1c6e37
FB
1022void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
1023{
1024 glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
1025}
1026
1027void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
1028{
1029 T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
1030}
1031
367e86e8
FB
1032#undef DATA_BITS
1033#undef SHIFT_MASK
1034#undef SIGN_MASK
1035#undef DATA_TYPE
1036#undef DATA_STYPE
1037#undef DATA_MASK
1038#undef SUFFIX